PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : fork, signal problematik



klewan
01-05-2006, 11:57
hallo, ich hab in etwa folgenden code





int running;
void sched_reaper(int signum) {
int status;
while (waitpid (-1, &status, WNOHANG) > 0) {

}
running--;
}


running=0;
signal(SIGCHLD, reaper);
for(x=0; x<10; x++) {
child_pid=fork();
switch(child_pid) {
case -1:
_log("FORK Error");
return -1;
break;
case 0:
signal(SIGCHLD, reaper);
//bisschen code
exit(0);
break;

default:
running++;


}
while(running != 0) {
printf("waiting...");
}

mein problem is das dies zu 99.9% gut geht aber ab und an wird anscheinend kein sigchld ausgelöst, dann wenn der child-code irgendwie abkackt (externer code) den ich mal, was dann zu folge hat das "running" z.b.: 1 ist obwohl kein process mehr läuft


meine frage:
im gdb hab ichs nicht gebacken bekommen fork()'s zu debuggen, bzw die signal's zu sehen, irgend eine idee?

welche signal's muss ein child abfangen, ich denk da z.b. an den fall das der child code segfault'ed (sollt zwar nicht sein, aber ist externer code)

7.e.Q
02-05-2006, 09:45
Auch bei 'nem SegFault sollte (Developer's Best Friend: "Sollte eigentlich gehen") immer ein SIGCHLD im Parent aufschlagen.

klewan
02-05-2006, 11:32
hmmmmpf
wie kann dann ne abweichung, also nicht 0, in current_running rauskommen

wie kann man man das SIGCHLD verhindern? (ähhh ungewollt *fg*) ;)

RapidMax
03-05-2006, 23:37
mein problem is das dies zu 99.9% gut geht aber ab und an wird anscheinend kein sigchld ausgelöst, dann wenn der child-code irgendwie abkackt (externer code) den ich mal, was dann zu folge hat das "running" z.b.: 1 ist obwohl kein process mehr läuft


Hmm, könnte es sein, dass ein Signal verlohren get? Dann würde allenfalls POSIX 1003.1b Signale helfen. (siehe sigaction). Zudem überprüfst du den Rückgabewert von waitpid() nicht auf Fehler (-1, siehe manpage).



while(running != 0) {
printf("waiting...");
}


Hier ist es sicherer auf running <= 0 zu prüfen.

Eine Alternative zu dem SIGCHLD Signal-Handler könnte in diesem Fall auch sein, dass du dieses Signal default-mässig ignorierst und stattdessen mit waitpid(-1, ..., WNOHANG); so lange wartest, bis alle gestarteten Prozesse sich beendet haben. Entweder du dekrementierst dabei wie gehabt running, oder du führt explizit eine Liste von child-pids und wartest mit waitpid(childpids[n], ..., WNOHANG) auf jeden Prozess einzeln. Ich empfehle WNOHANG, da sonst Zombies entstehen.



meine frage:
im gdb hab ichs nicht gebacken bekommen fork()'s zu debuggen, bzw die signal's zu sehen, irgend eine idee?


Eigentlich müsste das mit "set follow-fork-mode child" funktionieren, leider ist diese Funktion ing gdb irgendwie nicht implementiert. Ich behelfe mir damit, dass ich nach dem fork() ein sleep(30) einfüge, um genug Zeit zu haben, mit gdb auf die neue pid zu attachen.



welche signal's muss ein child abfangen, ich denk da z.b. an den fall das der child code segfault'ed (sollt zwar nicht sein, aber ist externer code)

Das child muss keine speziellen Signale abfangen. Natürlich ist es immer sinnvoll, bei einem SIGTERM noch sauber aufzuräumen. SIGSEGV abzufangen mach selten Sinn, hier sollte auf jeden Fall beendet werden, und vor allem eine Programminternen Strukturen mehr angefasst werden. Ich habe z.B. ein System, bei dem einige Prozesse mit waitpid(-1, &status, WNOHANG) überwacht werden, und im Fehlerfall neu gestartet werden. In diesem übergeordneten Prozess überprüfe ich über die "status"-Variable, ob der Prozess mit SIGSEGV beendet worden ist und logge dieses Ereigniss.

Gruss, Andy

klewan
05-05-2006, 13:24
meld mich wieda wenn ich die manpage verstanden hab ;-D