当STDIN文件描述符传递时,哪个进程接收Ctrl+C的SIGINT信号?
核心问题:Ctrl+C信号的接收进程与传递机制
场景概述
该应用基于命令行界面运行:用户启动客户端,客户端向服务器发送命令、打印响应后终止;服务器收到请求后找到对应的worker可执行文件,通过fork-and-exec启动它并等待执行完成,随后构造响应返回给客户端。
关键复杂点
- 若服务器未运行,客户端会启动服务器(每个用户对应一个独立的服务器进程);服务器被fork-and-exec启动时,fork出的子进程会调用
daemon(0, 0),再完成后续初始化并执行程序。 - 客户端通过Unix套接字(格式如
@server_name)发送请求时,会传递标准I/O的三个文件描述符。
Worker进程的I/O重定向实现
服务器fork-and-exec启动worker时,会将worker的标准I/O重定向到从客户端接收的三个文件描述符,核心代码如下:
// fork()后的子进程代码 auto new_fd = fcntl(received_fd, F_DUPFD_CLOEXEC, 3); dup2(new_fd, channel); // channel为0、1或2
注:这段代码会分别处理STDIN、STDOUT、STDERR三个文件描述符;worker后续创建的子进程不会继承STDIN。
初始理解误区
原本的认知是:Bash shell捕获Ctrl+C后,会生成并发送SIGINT信号给与Bash同会话ID的进程,即客户端;而服务器因调用daemon(0,0)已脱离Bash会话,会话ID不同,因此服务器及worker进程不会收到信号。但实际观测到worker似乎收到了信号,无法确认客户端是否收到,也疑惑仅通过共享标准输入,Ctrl+C的SIGINT信号为何能传递给worker。
最终排查结论
经深入排查确认:客户端确实会捕获SIGINT信号并终止,导致套接字连接断开;服务器检测到文件描述符失效后,会向对应的worker进程发送信号,这才是worker看似从终端收到信号的真正原因。
内容的提问来源于stack exchange,提问作者Stephen
相关产品推荐
相关产品推荐

