这是一个使用pthreads、bind、listen和accept的标准C++ TCP服务器程序。我碰到了这样的情况:当我杀死连接的客户端时,服务器会崩溃(也就是退出)。
崩溃的原因是write()
对文件的调用失败了,从而导致程序接收到SIGPIPE信号。我猜这是导致服务器退出的原因。
我想,“当然,未处理的信号意味着退出”,那么让我们使用signal()
:
signal(SIGPIPE, SIG_IGN);
因为以下引自 man 2 write
:
EPIPE fd 连接了一个读端关闭的管道或socket。当这种情况发生时,写进程将会收到一个SIGPIPE信号 (因此,write返回值只有在程序捕获、阻塞或忽略该信号时才能看到)。
然而,无论是在服务器线程还是客户端线程中,这似乎都没有帮助。
那么,我该如何防止 write()
调用引起该信号,或者(为实际起见)如何防止服务器退出。
我的诊断结果是:
- 启动服务器线程,绑定、监听、接受。
- 让客户端连接(例如通过telnet)
- 发送
pkill telnet
以使客户端崩溃
不期望的行为:服务器退出,在gdb中如下:
... in write () at ../sysdeps/unix/syscall-template.S:82
82 T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS)
以及 回溯信息:
#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 ?? ()
select()
。我会仔细检查写入调用()的。 - towisignal()
的 man 手册说:“在多线程进程中使用signal()
的效果是未指定的”,并建议使用sigaction()
代替。(但是思路是相同的。) - Julien-L