Comment engendrer des processus enfants qui ne meurent pas avec un parent?

J’ai un programme C ++ qui agit comme un chien de garde sur les autres. S’il détecte qu’un processus ne fonctionne plus, il le redémarre via le system . Le problème est que si je tue le processus de surveillance, tous les processus qu’il a démarrés meurent également.

 void* ProcessWatchdog::worker(void* arg) { //Check if process is running if( !processRunning ) system("processName /path/to/processConfig.xml &"); } 

Le nouveau processus enfant démarre correctement et s’exécute sans problème. Mais lorsque le parent (maintenant ce processus ProcessWatchdog ) meurt, l’enfant meurt aussi. Comment puis-je engendrer un processus enfant totalement indépendant du parent?

J’ai essayé d’utiliser pclose et popen , d’exécuter des scripts shell qui lancent des processus et quelques autres tactiques, mais en vain. SIGHUP signaux SIGHUP dans les processus enfants, mais ils meurent toujours.

Donc, idéalement, je voudrais dire au système de lancer un processus totalement indépendant du parent. Je veux que la trace de l’enfant se termine avec l’enfant et que le système n’ait aucune idée que ProcessWatchdog démarré en premier lieu.

Y a-t-il un moyen de le faire?

J’écris ceci en C ++, sous Linux.

Essayez d’utiliser le system avec setsid avant le nom du processus.

 system("setsid processname /path/to/processConfig.xml &"); 

Cela lancera le programme dans une nouvelle session.

Celui-ci est un peu vieux mais n’a pas reçu de réponse complète. Voici ce que j’ai fait sur un système embarqué pour engendrer un enfant bash sans relation avec le parent. Notez que j’exécute un shell bash, puis exécute ma commande dans un autre shell bash. Cela peut ne pas être nécessaire dans votre situation. Pour moi, cela m’a permis de faire une redirection d’E / S qui ne fonctionnait pas correctement sans elle.

Les deux concepts importants sont setsid () et double fork (). La combinaison de ces deux éléments empêche la création d’un zombie à la fin de l’enfant orphelin et empêche que l’enfant orphelin soit tué si le parent termine.

Il y a beaucoup d’autres problèmes qui pourraient survenir, comme les poignées d’E / S héritées, le répertoire de travail, etc., mais ce code fait le travail de base.

 int spawn_orphan(char* cmd) { char command[1024]; // We could segfault if cmd is longer than 1000 bytes or so int pid; int Stat; pid = fork(); if (pid < 0) { perror("FORK FAILED\n"); return pid; } if (pid == 0) { // CHILD setsid(); // Make this process the session leader of a new session pid = fork(); if (pid < 0) { printf("FORK FAILED\n"); exit(1); } if (pid == 0) { // GRANDCHILD sprintf(command,"bash -c '%s'",cmd); execl("/bin/bash", "bash", "-c", command, NULL); // Only returns on error perror("execl failed"); exit(1); } exit(0); // SUCCESS (This child is reaped below with waitpid()) } // Reap the child, leaving the grandchild to be inherited by init waitpid(pid, &Stat, 0); if ( WIFEXITED(Stat) && (WEXITSTATUS(Stat) == 0) ) { return 0; // Child forked and exited successfully } else { perror("failed to spawn orphan\n"); return -1; } } 

Ne pas utiliser le system(...) il n’est pas multi-threading safe.

 int pid = fork(); if(pid==0) { int rc = execv("processname", "/path/to/processConfig.xml &"); if(rc == -1) { printf(stderr, "processname failed to start. %d", errno); } ... } else { //continue with the parent } 

Vous devriez éviter l’utilisation du système.

N’utilisez pas system () à partir d’un programme avec des privilèges set-user-ID ou set-group-ID, car des valeurs étranges pour certaines variables d’environnement peuvent être utilisées pour renverser l’intégrité du système. Utilisez plutôt la famille de fonctions exec (3).

et aussi si vous voulez vérifier la valeur de retour ou autre chose

Allez juste pour execl

 #include  #include  pid_t pid = fork() if (pid == -1) { exit(EXIT_FAILURE); } else if (pid == 0) { if (execl("processname", "processname", "/path/to/processConfig.xml", NULL) == -1) exit(EXIT_FAILURE); } else ... 

Vous pouvez être intéressé par la fonction de bibliothèque daemon (3) (utilisant en interne deux appels système nesteds fork (2) ). Après cela, utilisez l’appel système approprié execve (2) (ou les fonctions exec (3) associées) …

Vous devriez lire Advanced Linux Programming pour plus d’informations.

Il y a un exemple execvp dans https://github.com/wALLe/wash/blob/master/src/wash.cpp . Passer des arguments en ligne de commande est parfois un problème avec les fonctions exec * d’Unistd et le passage de l’environnement peut être un problème. En tout cas, j’espère que ça aide …