2013-07-11 13 views
5

Ich habe ein C++ - Programm, das als Wachhund gegenüber anderen fungiert. Wenn festgestellt wird, dass ein Prozess nicht mehr ausgeführt wird, wird er über system neu gestartet. Das Problem ist, dass, wenn ich den Watchdog-Prozess abbringe, alle Prozesse, die er gestartet hat, auch sterben.Wie spuckt man Child-Prozesse, die nicht mit Eltern sterben?

Der neue untergeordnete Prozess wird ordnungsgemäß gestartet und kann ohne Probleme ausgeführt werden. Aber wenn der Elternteil stirbt (jetzt dieser ProcessWatchdog Prozess), stirbt auch das Kind. Wie kann ich einen Child-Prozess erzeugen, der völlig unabhängig von dem Elternteil ist?

Ich habe versucht mit pclose und popen, laufende Shell-Skripte, die Prozesse starten, und ein paar andere Taktiken, aber ohne Erfolg. Ich ignoriere SIGHUP Signale in den Kind-Prozessen, aber sie sterben immer noch.

Idealerweise möchte ich dem System mitteilen, dass es einen Prozess starten soll, der völlig unabhängig von den Eltern ist. Ich will, dass die trace des Kindes mit dem Kind endet, und für es/das System keine Ahnung hat, dass ProcessWatchdog es in erster Linie gestartet hat.

Gibt es eine Möglichkeit, das kann ich tun?

Ich schreibe dies in C++, auf Linux.

+0

möglich duplicate von [Machen Sie Kind-Prozess mit dem System launched() weiter, nachdem Eltern bekommt Kill-Signale und Ausgänge] (http://stackoverflow.com/questions/12945189/make-child- process-launched-with-system-keep-running-nachher-parent-gets-kill-sig) –

+0

Ich glaube nicht, System zu verwenden ist eine gute Idee .... – Alexis

+0

Warum ist das System nicht eine gute Idee? Neben den offensichtlichen Sicherheitsproblemen? Ich mache das auf einem eingebetteten System in einer sehr kontrollierten Umgebung, und ich mache mir keine Sorgen über fehlerhafte Systemaufrufe. Gibt es einen anderen Grund, warum ich vorsichtig sein sollte? –

Antwort

0

Versuchen system mit setsid vor dem Prozessnamen.

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

Dadurch wird das Programm in einer neuen Sitzung gestartet.

3

Verwenden Sie nicht system(...) es ist nicht Multithreading sicher.

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 
} 
+3

Können Sie "Nicht Multi-Threading sicher" näher ausführen? –

+0

execv brauche ein char ** im zweiten param – Alexis

1

Sie sollten die Verwendung von System vermeiden.

Verwenden System nicht() von einem Programm mit Set-User-ID oder Set-Gruppe-ID Privilegien, weil seltsame Werte für einige Umgebungsvariablen könnten zu unterminieren Systemintegrität verwendet werden. Verwenden Sie stattdessen die exec (3) -Familie der -Funktionen.

und auch, wenn Sie überprüfen möchten, gehen Sie den Rückgabewert oder irgendetwas anderes

Just for execl

#include <unistd.h> 
#include <stdlib.h> 
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 
... 
4

Dieser ist ein bisschen alt, bekam aber keine vollständige Antwort. Hier ist, was ich in einem eingebetteten System getan habe, um ein Bash-Kind zu erzeugen, das keine Beziehung zum Elternteil hat. Beachten Sie, dass ich eine Bash-Shell ausführen und dann meinen Befehl in einer anderen Bash-Shell ausführen werde. Dies ist möglicherweise in Ihrer Situation nicht notwendig. Für mich erlaubte es mir, eine I/O-Umleitung zu machen, die ohne sie nicht richtig funktionierte.

Die beiden wichtigen Konzepte sind die setsid() und die doppelte fork(). Die Kombination dieser beiden verhindert, dass ein Zombie erstellt wird, wenn das verwaiste Kind fertig ist, und verhindert, dass das verwaiste Kind getötet wird, wenn das Elternteil fertig ist.

Es gibt viele andere Probleme, die auftreten können, wie geerbte E/A-Handles, Arbeitsverzeichnis usw., aber dieser Code erledigt die grundlegende Aufgabe.

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; 
    } 
}