Re: Suche Debughilfe: child never returns from fork?

From: Oliver Fromme <olli(at)lurza.secnetix.de>
Date: Tue, 8 Apr 2008 12:15:24 +0200 (CEST)

Hallo,

Ergänzend zu dem, was Bernd bereits schrieb ...

Peter Much wrote:
> > switch (bpipe->worker_pid = fork()) {
> > case -1: /* error */
> ... etc. etc. ...
> > case 0: /* child */
> > close(readp[0]); /* Close unused child fds */
> > dup2(readp[1], 1); /* dup our read to his stdout */
> > dup2(readp[1], 2); /* and his stderr */
> ... etc. etc. und irgendwann dann execvp()
> > default: /* parent */
> > break;
> > }
> ... etc. etc. ...
>
> Passieren tut dabei folgendes:
> - der fork() wird ausgeführt, ich hab also zweimal dasselbe Programm
> mit unterschiedlicher PID in der Prozessliste.
> - der Parent läuft normal weiter und macht seine Arbeit wie
> vorgesehen.
> - das Child steht im Status "Running" und braucht 100% system-cpu,
> und ist dementsprechend nur mit -9 killbar.

Das Wörtchen »dementsprechend« kann ich hier nicht nach-
vollziehen.

Selbstverständlich sollte auch ein Prozess, der 100% CPU
verbrät, mit einem ganz normalen kill (d.g. SIGTERM) ab-
gebrochen werden können, es sei denn, Du ignorierst das
Signal ausdrücklich oder hast einen Handler dafür instal-
liert.

Wenn Du das nicht hast und trotzdem ein SIGKILL brauchst,
dann ist da was faul.

Bist Du sicher, dass _jeder_ case-Zweig ein break am Ende
hat? Das kann jedem mal passieren, dass man das vergisst,
und man findet solche Fehler ums Verrecken nicht, auch
wenn man tausendmal drüberschaut. Been there, done that.
GCC's Warnungen sind leider auch nicht immer hilfreich.

> Wie kann man sowas debuggen?

Compilier das Programm mit Debug-Informationen. Wenn das
Child wieder mal hängt, schick ihm ein SIGABRT oder SIG-
QUIT, damit es einen Coredump schreibt. Den kannst Du
dann mit gdb nach Herzenslust debuggen (Stacktrace, Vari-
ablenwerte angucken usw.).

Als letzte Möglichkeit kannst Du noch versuchen, mit einem
der Trace-Tools (ktrace, strace, truss) zu gucken, was der
Prozess gerade tut. Das hilft aber nur dann, wenn er auch
Syscalls aufruft. Wenn er in einer Userland-Endlosschleife
hängt, siehst Du da nichts. In dem Fall würde evtl. noch
dTrace helfen, aber das gibt's erst demnächst in 8-current.

Und noch ein Tipp: Vergleich doch mal Deine Implementation
(zumindest den fork-Teil) mit der von popen(3). Offenbar
scheinst Du ja etwas ganz ähnliches machen zu wollen.
Siehe: /usr/src/lib/libc/gen/popen.c

Gruß
   Olli

-- 
Oliver Fromme, secnetix GmbH & Co. KG, Marktplatz 29, 85567 Grafing b. M.
Handelsregister: Registergericht Muenchen, HRA 74606,  Geschäftsfuehrung:
secnetix Verwaltungsgesellsch. mbH, Handelsregister: Registergericht Mün-
chen, HRB 125758,  Geschäftsführer: Maik Bachmann, Olaf Erb, Ralf Gebhart
FreeBSD-Dienstleistungen, -Produkte und mehr:  http://www.secnetix.de/bsd
PI:
int f[9814],b,c=9814,g,i;long a=1e4,d,e,h;
main(){for(;b=c,c-=14;i=printf("%04d",e+d/a),e=d%a)
while(g=--b*2)d=h*b+a*(i?f[b]:a/5),h=d/--g,f[b]=d%g;}
To Unsubscribe: send mail to majordomo(at)de.FreeBSD.org
with "unsubscribe de-bsd-questions" in the body of the message
Received on Tue 08 Apr 2008 - 12:15:48 CEST

search this site