Ein ganz normales C++-TCP-Serverprogramm, das verwendet wird pthreads, binden, Hören und annehmen. Ich habe das Szenario, dass die Server endet (sprich: stürzt ab), wenn ich einen verbundenen Client beende.
Der Grund für den Absturz ist, dass die write()
rufen Sie an Datei schlägt fehl, daher erhält das Programm ein SIGPIPE. Und ich schätze, dadurch wird der Server beendet.
Ich dachte, “natürlich bedeutet unbehandeltes Signal Ausgang”, also lasst uns verwenden signal()
:
signal(SIGPIPE, SIG_IGN);
weil, genommen von man 2 write
:
EPIPE fd an ein Rohr oder eine Muffe angeschlossen ist, deren lesendes Ende geschlossen ist. Wenn dies geschieht, erhält der Schreibvorgang auch ein SIGPIPE-Signal. (Daher wird der Write-Rückgabewert nur gesehen, wenn das Programm dieses Signal abfängt, blockiert oder ignoriert.)
Leider nein. Weder im Server-Thread noch in den Client-Threads scheint dies zu helfen.
So, wie verhindere ich das write()
Anruf davon abhält, dieses Signal auszulösen, oder (um pragmatisch zu sein) wie verhindere ich, dass der Server beendet wird.
Meine Diagnosen sind:
- Server-Thread gestartet, Bindung, Überwachung, Annahme.
- Lassen Sie einen Client eine Verbindung herstellen (z. B. über Telnet)
- Sende ein
pkill telnet
den Client zum Absturz bringen
unerwünschtes Verhalten: Server beendet, in gdb mit
... in write () at ../sysdeps/unix/syscall-template.S:82
82 T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS)
und die zurückverfolgen:
#0 ... in write () at ../sysdeps/unix/syscall-template.S:82
#1 ... in ClientHandler::mesg(std::string) ()
#2 ... in ClientHandler::handle() ()
#3 ... in start_thread (arg=<value optimized out>) at pthread_create.c:300
#4 ... in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112
#5 ... in ?? ()
Ich vermute hier, aber vielleicht müssen Sie den Dateideskriptor/Socket mit dem O_NOCTTY-Flag erstellen?
– Vinicius Kamakura
25. Juli 2011 um 20:20 Uhr
@hexa: Es ist unwahrscheinlich, dass O_NOCTTY etwas damit zu tun hat.
– Jonathan Leffler
25. Juli 2011 um 20:56 Uhr
Signal (SIGPIPE, SIG_IGN) ist das, was Sie wollen. Die eigentliche Frage ist, warum es bei dir nicht funktioniert. Vielleicht kehrt ein anderer Code seine Wirkung um, indem er einen separaten Signalhandler installiert? Oder ist es vielleicht nur so, dass Ihre Argumente für write() falsch sind und einen guten altmodischen Absturz verursachen (nicht im Zusammenhang mit SIGPIPE)?
– Jeremy Friesner
25. Juli 2011 um 21:59 Uhr
@Jeremy: Kein anderer Signalhandler, nur a
select()
. Und ich werde den Write-Call() dbl-checken.– towi
26. Juli 2011 um 6:43 Uhr
@JeremyFriesner: Manpage für
signal()
sagt, dass “die Wirkung vonsignal()
in einem Multithread-Prozess sind unspezifiziert” und empfiehlt die Verwendungsigaction()
stattdessen. (Aber die Idee ist die gleiche.)– Julien-L
10. April 2013 um 0:04 Uhr