Re: Suche Debughilfe: child never returns from fork?

From: Bernd Walter <ticso(at)cicely12.cicely.de>
Date: Wed, 9 Apr 2008 13:43:32 +0200

On Tue, Apr 08, 2008 at 07:47:38PM +0000, Peter Much wrote:
> <ticso(at)cicely.de> aka Bernd Walter schrieb
> mit Datum Tue, 8 Apr 2008 00:32:24 +0200 in m2n.de.fbsd.questions:
> |Wenn der tatsächlich beim close hängt, dann stellt sich mir zwangsläufig
> |auch die Frage was das für Filehandles sind.
> |Das Problem mag ja durchaus am Medium der Files liegen.
>
> Gute Frage. Die wurden unmittelbar vorher mit pipe() beschafft.

Pipes funktionieren unter FreeBSD sehr viels anders, als unter Linux.
Und auch ansonsten gibt es viele Dinge, die gerne vergessen werden,
z.B. ist der Buffer einer Pipe nicht unter jedem OS gleich, was
aber schnell mal zu hängern führen kann.
Ich selber benutze meist einfach socketpair(2), was weniger OS
spezifisch ist und mehr Einstellmöglichkeiten erlaubt.
>
> Und, ich hab mal das close() durch ein open() ersetzt - das taucht
> auch nicht auf - also entweder bleibt er auch im Eingang von dem
> open() hängen, oder er kommt doch schon aus dem fork() nicht raus.

Also, dass der schon beim fork selber Ärger macht ist schon ziemlich
ungewöhnlich.
Ist das Programm gegen eine Thread-Library gelinked?
Obwohl selbst dabei sollte der fork eigentlich durchlaufen.

> |> Jetzt kommt die Widerlichkeit: das Zeug läuft 500 mal korrekt ab, und
> |> dann bleibt es -unvorhersagbar- irgendwann einmal hängen. Aber das auch
> |> immer wieder mal - d.h. alle paar Tage. Und auf einer anderen,
> |> installationsgleichen aber deutlich schnelleren (und weniger
> |> vollgepackten) Maschine ist es nur einmal passiert.
> |
> |Na gut - solche Programmfehler wären nichts neues.
>
> Aye. Ich such auch nicht nach nem Schuldigen. Nur nach nem
> akzeptablen Fix, und vor allem nach Verstehen.

Die Suche nach dem Schuldigen ist manchmal ausreichend.
Wenn man z.B. erkennt, dass der Programmcode ohne ausreichend
Hintergrundwissen geschrieben wurde, dann kann es einen kompletten
review erfordern oder dazu führen die Software nicht einzusetzen.

> |> Der Fehler ist plötzlich aufgetaucht nachdem die Maschinen auf
> |> RELEASE 6.3 upgraded wurden (zuvor: RELEASE 5.5, mit identischen
> |> Ports).
> |
> |Auch das wäre nichts neues.
>
> Hm. Leider. :-/
> Muss ich sagen, dass ich von 6.3 nicht übermäßig begeistert bin?
> (Ich bau seit vier Monaten Bugs raus. Aus *allem* - Ports, User,
> Kernel, Scripts, aus meinem Kopf;), ...)

Ich kann mich nicht an sonderlich viel erinnern.

> Das fällt aber unter P.P.; braucht nicht als Kritik verstanden zu
> werden. Ich weiss ehrlich gesagt nicht worans liegt - vielleicht werd
> ich einfach langsam alt...
>
> |> Ich kann natürlich nicht sagen, ob der Prozess aus dem fork() nicht
> |> raus- oder in den close() nicht reinkommt. Mir ist auch klar, dass
> |> der fork() derweil milliardenmal richtig ausgeführt wird...
> |
> |Du hast beim case -1 auch sauber abgefangen, dass der nicht in den
> |case 0 durchfällt?
>
> Das sieht so aus, ja.
>
> |Und so Klassiker, wie sigchld hast du auch sauber behandelt?
>
> Ich nix wissen. Ich habs nicht geschrieben. Es heißt Bacula
> (in diesem Fall der Client), und ist konzeptionell die beste
> Backup-Strategie die mir in Freeware bislang untergekommen ist
> - in der Ausgestaltung muss halt noch ein Stück Arbeit reingesteckt
> werden.
> Aber das find ich besser als andersrum... hat so die Qualität
> eines sendmail: man kann beinahe alles biegen, aber oft nicht
> ganz so wie man sichs vorstellt...

Bacuala ist in der Vergangenheit schon mehrfach aufgefallen unsauber
zu sein.

> Allerdings passieren mit dieser Software noch andere komische
> Sachen, die ich auch nicht so ganz verstehe...

Das Gefühl kenne ich - meist kommt es daher, dass etwas gemacht wird,
was man selber niemals so tun würde, weil es kompletter Unfug ist.

> Z.B. wenn ich den Server (korrekt) mit SigTERM beenden will,
> dann geht er geht in eine Endlosschleife und beendet sich erst
> mit einem weiteren SigTERM. Ich hab in der Userbase gefragt wem
> es noch so geht, aber keiner von den (weitestgehend Pinguin-)Usern
> konnte es reproduzieren.
>
> Dann hab ich im Code gesucht und finde ein Konstrukt dieser Art:
> while(c = next(c)) free(c);
> Das ist ja kein Problem. Blöd ist dabei nur, wenn
> 1. die Zeiger selber im freizugebenden Speicherbereich rumzuliegen
> scheinen (das ist zur Hälfte irgendwelches objektorientiertes C,
> und mithin nicht so genau auszumachen), und

Eben - das sind ein user-after-free in einer einzigen Zeile.
Sowas ist einfach nur Megapeinlich und stellt für mich den Rest des
Sourcecodes umso mehr in Frage.

> 2. man dabei das free() umdefiniert hat und ein eigenes free verwendet
> das den Space vorsichtshalber erst noch überschreibt -
> (intelligenterweise dann gleich mit 0xaaaaaaaa, sodass man
> den Müll wenigstens sieht wenn man die Adressen ausgeben läßt).
>
> Interessant sind allerdings zwei Fragen:
> 1. wieso macht sowas den Pinguinen nichts aus, und
> 2. wieso geht im FreeBSD dabei der Prozess in eine Endlosschleife?
>
> Nächste interessante Frage: zur Fehlerbehandlung bei Null-Pointer-
> Referenzen wird folgender Code verwendet:
>
> if (type == M_ABORT) {
> char *p = 0;
> p[0] = 0; /* generate segmentation violation */
> }
>
> Auch hier geht das Programm unter FreeBSD in eine Endlosschleife.
> Und das scheint nun wiederum mit genau 37 verbogenen Signalhandlern
> zu tun zu haben die man da zu brauchen meint...

Sehe ich aus so.
Mit sighandlern kann man sich schnell die Karten legen.
Die Frage ist nur, ob ich jemanden, der das obige while Konstrukt
verwended überhaupt zutrauen kann sighandler zu schreiben.

> Es scheint sich da so zu verhalten, wenn das Programm auf ein SigTERM
> hin beendet wird, und derweil die SEGV erfolgt, dass dann das
> Programm weder crasht noch beendet, sondern endlosschleift. Irgendwie
> nicht wirklich sinnvoll - da muss es doch brauchbarere Optionen
> geben...

Das passt natürlich.
Kaskadierte Sighandler sind nicht ohne.

> Und dann kommt mir der leise Verdacht, dass es sich bei dem
> hängenbleibenden fork zwar nicht um das gleiche (denn diese
> Spielchen sind immerhin mit einem weiteren SigTERM abstellbar),
> aber um etwas verwandtes handeln könnte... hm, nicht wirklich
> erfreulich...
>
> Und immer noch die Frage: warum stört sowas die Pinguine nicht?

Weil die Jungs unsauber programmiert haben und damit zig Probleme
heraufbeschwören.
Einige der Fehler sind halt falsche OS Erwartungen, die unter Linux
erfüllt werden.
Z.B. scheint Linux auf einen memory fault innerhalb einer Memory-Fault
Handlers anders zu reagieren.
Ich verstehe aber auch den ganzen Sinn des Abort-Handlers nicht.

> |> Wie kann man sowas debuggen?
> |
> |Wenn der Prozess unkillbar ist, dann hilft der Kernel-Debugger, um dort
> |zu sehen wo der Prozess gerade steckt.
> |Mitunter muss man das mehrfach machen, um ein Gefühl dafür zu bekommen,
> |da der ja schließlich in irgendeiner Form imme rnoch läuft.
>
> Hmja, gute Idee. Hab ich glaub ich nur ansatzweise vor laaanger
> Zeit mal gemacht, und auf die schnelle auch keine brauchbare
> Anleitung gefunden. (Das geht alles nur in Richtung remote und mit
> symboltabelle(*) und riesenaufwand usw. usf.)

Gehe am besten auf Olivers Hinweise zurück.
Ich hatte nur kill -9 gelesen und gedacht der beended sich gar nicht.

> (*) Andere Frage:
> Ich versteh nicht warum alle welt meint man solle erstmal
> "makeoptions DEBUG=-g" einschalten - ich hab beim Probieren
> (bzgl. kern/122126) erlebt, dass das bewirkt, dass der Kernel
> im falle einer panic gleich mehrere davon macht und dann nicht
> mehr rebootet sondern steckenbleibt - also KDB und KDB_UNATTENDED
> funktioniert dann nicht mehr.

-g bewirkt mit Sicherheits nichts von dem.
Alles, was passiert ist, dass Debuginformationen mitgeschrieben
werden, z.B. von welcher Programmzeile welcher Code kommt.
Das wird aber nebenher geschrieben und steckt zwar im Binary drin,
wird aber nicht in den Speicher geladen.
Man benutzt das beim Kernel ausschließlich zum analysieren von
Crashdumps.

> Man kommt dann weder in den KDB (falls man on-site ist) noch kriegt
> man einen Reboot und damit seine Connectivity wieder (falls man
> off-site ist). Und einen dump (wenn man denn einen wollte) gibts
> dann scheinbar auch nicht.
> Und das finde ich so ziemlich, äh, unwünschenswert - und wirklich
> nur auf Testsystemen vertretbar...

Kann ich verstehen, aber das hat andere Ursachen.

-- 
B.Walter <bernd@bwct.de> http://www.bwct.de
Modbus/TCP Ethernet I/O Baugruppen, ARM basierte FreeBSD Rechner uvm.
To Unsubscribe: send mail to majordomo(at)de.FreeBSD.org
with "unsubscribe de-bsd-questions" in the body of the message
Received on Wed 09 Apr 2008 - 13:44:18 CEST

search this site