2009-08-14 5 views
1

Unter Solaris 9 und 10, die beide x86 und Sparc hängen, haben wir einen Prozess, der während der Ausgang hängt:Solaris Prozess in Ausfahrt

fe0b5994 lwp_park (0, 0, 0) 
fe0b206c slow_lock (ff388908, fe080400, 0, 0, 98, fe0abe00) + 58 
ff376aa8 __deregister_frame_info_bases (2a518, 1, 0, 2daf0, 0, ff376be4) + 4c 
00014858 ???????? (0, ff000000, 0, 0, 0, 0) 
00019920 _fini (0, 0, 210fc, fe21cbf0, 5, fe25897c) + 4 
fe21cbf0 _exithandle (fee66a4c, 0, 40, 0, 0, fe2bc000) + 70 
fe2a0564 exit  (0, fdefb47c, 40, fdefb8ff, 2c, 0) + 24 
fee66a4c (our code) (4e280, 5ab5c, 5aa60, 2ed0, 81010100, fdefb988) + 244 

Unser Code auf der Solaris 9 Maschine kompiliert wird, gcc 3.4. 6.

Der fragliche Prozess ist ein Singlethread-Kind aus einem Multi-Thread-Elternteil, fork ed, aber nicht exec Ed.

Hat jemand etwas ähnliches gesehen?

Wissen Sie, ob eine neuere Version von gcc das Problem beheben würde?

Antwort

2

Sie könnten versuchen, _exit() aufrufen, um den untergeordneten Prozess statt exit() zu beenden. exit() ist eine Bibliotheksfunktion, die verschiedene Formen der Bibliotheksbereinigung vor dem Beenden ausführt - beispielsweise werden die stdio-Puffer auf den Datenträger geleert. _exit() ist der eigentliche Systemaufruf, der den Prozess beendet. Selbst in Singlethread-Programmen haben Sie normalerweise _exit() in gegabelten Kindern verwendet, um zu verhindern, dass die Bibliothek zweimal aufräumt.

+0

Gute Idee - Ich habe alle Exit-Aufrufe in diesem Codeabschnitt in _exit geändert. –

+0

Die offizielle Single UNIX-Spezifikation besagt, dass _exit() und nicht exit() nach einem fork() - http://www.opengroup.org/pubs/online/7908799/xsh/vfork.html verwendet werden soll –

1

Genau deshalb sollten Sie in einem MT-Prozess immer nach fork vorgehen: Sie wissen nicht, was andere Threads sperrt, die im Parent gehalten werden, und wann Sie eine dieser Sperren benötigen. Hier brauchen Sie einen beim Beenden, aber Sie können ihn nicht bekommen, weil der Thread, der ihn gesperrt hat, nicht im Kind existiert.

Neue Version von GCC ist etwas unwahrscheinlich, Ihnen zu helfen. Selbst wenn es hilft, ist es nur eine Frage der Zeit, bis Sie ein anderes Schloss wie dieses schlagen.

Entweder Gabel vor dem Erstellen des ersten Threads oder Exec unmittelbar nach Gabel. Dies sind wirklich die einzig sinnvollen Entscheidungen.

+0

Ich denke, du hast Recht - ich habe den gemeinsamen Pfad zu run/bin/true anstelle eines normalen Exits geändert - natürlich immer noch ein Problem, wenn execl() fehlschlägt. –