2016-05-23 9 views
1

In meinem Programm, das ich ein Einfrieren manchmal erhalten, wenn in diesem Fall nach stderr schreibt:Einfrieren beim Schreiben auf `stderr`

  1. Programm beginnt (zB von Terminal)
  2. Programm Gabeln sich zweimal und mit execvp um jeden Prozess mit verschiedenen Parametern zu starten (Originaldatei wird von /proc/self/exe gelesen)
  3. Das erste gestartete Programm wird beendet.
  4. Nun werden die beiden gegabelten Prozesse noch laufen
  5. das Terminal Schließen Sie das erste Programm
  6. ein paar Versuche gestartet wurde fprintf mit zu stderr Arbeit, auf einem gewissen Punkt schreiben ich auf meinem Programm eine komplette Überbrückungs bekommen. Debugger sagt mir seinen fprintf.

Was passiert hier? Was ich schon probiert habe, ist ein SIG_IGN auf SIGPIPE zu setzen, um den Programmabsturz zu verhindern, sobald niemand mehr auf die Pipes hört. Aber jetzt bin ich fest (das Verhalten mit dem Freeze ist das gleiche, mit SIG_IGN und ohne es).

Jede Hilfe wird geschätzt.

+2

_Fragen, die Debugging-Hilfe suchen ("Warum funktioniert dieser Code nicht?") Müssen das gewünschte Verhalten, ein bestimmtes Problem oder einen Fehler und den kürzesten Code enthalten, der für die Reproduktion in der Frage erforderlich ist. Fragen ohne eine klare Problemstellung sind für andere Leser nicht nützlich. Siehe: So erstellen Sie ein minimales, vollständiges und überprüfbares Beispiel._ –

+0

Die Frage wurde bereits beantwortet. – Nidhoegger

+0

Richtig, aber dennoch sollte es zukünftigen Lesern nützlich sein. Erklärung ist erforderlich, IMHO. –

Antwort

3

Auf den Punkt gebracht: Das System sendet Ihre Programmsignale, um Sie vor einem Problem zu schützen. Du ignorierst diese Signale. Schlimme Dinge passieren.

Wenn Ihr übergeordnetes Programm ausgeführt wurde, hatte es stdin (fd 0), stdout (fd 1) und stderr (fd 2) mit dem TTY der Shell verbunden, die Sie (das Terminal) lief. Diese funktionieren ähnlich wie Pfeifen. Wenn Sie das Terminal geschlossen haben, bleiben diese Fds hängen und niemand auf der anderen Seite, um mit ihnen kommunizieren zu können.

Zuerst passiert nichts Schlimmes. Sie schreiben nach stderr, und die Standardbibliothek speichert diese Schreibvorgänge zwischen. Es werden keine Systemaufrufe durchgeführt, also kein Problem.

Aber dann füllen sich die Puffer und stdlib versucht sie zu löschen. Wenn es das tut, füllt es die Kernel-Puffer für die Pipe oder TTY. Am Anfang funktioniert das auch gut. Früher oder später füllen sich diese Puffer jedoch auch. Wenn das passiert, unterbricht der Kernel Ihre Prozesse und wartet darauf, dass jemand vom anderen Ende dieser Pipes liest. Da Sie das Terminal jedoch geschlossen haben, wird dies nie passieren und Ihre Programme sind auf unbestimmte Zeit gesperrt.

Die Standardmethode zur Vermeidung dieses Problems besteht darin, die 0-2-Dateideskriptoren vom steuernden TTY zu trennen. Anstatt Ihnen zu sagen, wie das geht, möchte ich vorschlagen, dass das, was Sie hier zu tun versuchen, ein Programm ausführen, so dass es vollständig von einem TTY getrennt ist, einen Namen hat: daemonizing.

Check out this Frage für weitere Details, wie man das macht.

Edited hinzufügen:

Aus Ihrer Funktion nicht klar war, ob die Programme, die Sie sind execve ing Ihre eigenen sind oder nicht. Wenn dies nicht der Fall ist, beachten Sie bitte, dass viele Benutzerprogramme nicht als Daemon ausgeführt werden können. Die naheliegendste Einschränkung ist, dass, wenn ein Programm, das nicht mit einem TTY verbunden ist, eine TTY-Datei öffnet und es an open übergibt, dass TTY das steuernde TTY des Programms wird. Abhängig von den Umständen kann dies zu unerwarteten Ergebnissen führen.

+0

Vielen Dank, diese Erklärung hat mir sehr geholfen. Was ich trotzdem machen wollte, ist Log in eine Datei. Die Logout-Ausgabe zum Terminal ist während der Entwicklung nur vorübergehend. Ich schätze, das ist jetzt ein Zeichen, um das Programm stattdessen in eine Datei zu loggen :). Vielen Dank! – Nidhoegger

+0

@Nidhoegger, wenn Sie in eine Datei schreiben mit 'fprintf (stderr, ...)', beachten Sie die Semantik. Wenn stdio-Funktionen sehen, dass das Ziel kein TTY ist, werden sie leer, wenn die internen Puffer voll sind, nicht wenn sie ein EOL sehen ('\ n'). Abhängig von Ihrem Fall kann dies sein oder nicht, was Sie wollen. –

+0

* Sie schreiben in stderr, und die Standardbibliothek speichert diese Schreibvorgänge zwischen. * Nicht unbedingt. 'stderr' ist normalerweise völlig ungepuffert. Das Anhängen von 'strace' an den laufenden Prozess würde fast sicher zeigen, dass die Systemaufrufe an fd2 vorgenommen werden. –