父进程接收SIGINT时如何阻止信号传递给clone-execve创建的子进程
问题
是否存在实现方案,可在父进程收到SIGINT信号时,不向子进程发送该SIGINT信号?
示例代码如下:
父进程实现 main.c
#define _GNU_SOURCE #include <sys/mman.h> #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <sched.h> int run_python(void* arg){ (void) arg; char *const args[] = {"python3", "run.py", NULL }; execve("/usr/bin/python3", args, NULL); return 0; } int main(void){ char *stack = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 1234, 0); clone(run_python, stack + 4096, 0, NULL); sleep(10); return 0; }
子进程实现 run.py
import sys import time import signal f = open("output.output", 'w') def recieved_sigint(*args): print("Received sigint", file=f, flush=True) sys.exit(1) signal.signal(signal.SIGINT, recieved_sigint) while(True): print("Test", file=f, flush=True) time.sleep(1)
现象
编译运行main.c时按下Ctrl+C,run.py子进程也会收到SIGINT信号,输出文件中打印"Received sigint"字符串。
需求
对于通过clone-execve方式创建的子进程,如何配置才能实现父进程收到SIGINT时,该子进程不会收到同一信号?
实现方案
先明确核心原理:按下Ctrl+C触发的SIGINT不是父进程转发给子进程的,是终端驱动直接发送给当前终端前台进程组内所有进程的。默认用clone创建的子进程和父进程属于同一个进程组,因此会同时收到信号。
有两种无副作用的实现方式可选:
- 方案1:让子进程脱离前台进程组(推荐)
子进程调用execve之前,执行setpgid(0, 0)将自身设置为独立进程组的组长,就会脱离父进程所在的前台进程组,终端发送的SIGINT不会再投递到该子进程。
修改后的run_python函数代码如下:
这种方式不影响后续主动向子进程发送信号,是最符合进程隔离设计的方案。int run_python(void* arg){ (void) arg; // 子进程进入独立进程组,脱离终端前台进程组 if (setpgid(0, 0) == -1) { perror("setpgid failed"); exit(EXIT_FAILURE); } char *const args[] = {"python3", "run.py", NULL }; execve("/usr/bin/python3", args, NULL); perror("execve failed"); exit(EXIT_FAILURE); } - 方案2:子进程主动忽略
SIGINT
如果子进程不需要响应任何SIGINT信号,可以在execve之前直接将SIGINT的处理逻辑设置为忽略,即使子进程和父进程同组收到信号,也不会触发自定义的信号处理函数。
修改后的run_python函数代码如下:
该方案实现更简单,但子进程后续无法响应任何int run_python(void* arg){ (void) arg; // 子进程忽略SIGINT信号 signal(SIGINT, SIG_IGN); char *const args[] = {"python3", "run.py", NULL }; execve("/usr/bin/python3", args, NULL); perror("execve failed"); exit(EXIT_FAILURE); }SIGINT,适合不需要对子进程做信号控制的场景。
修改后重新编译运行,按下Ctrl+C时只有父进程会收到SIGINT退出,子进程会继续正常运行,output.output中不会出现Received sigint打印,符合预期。
内容的提问来源于stack exchange,提问作者St.Antario
相关产品推荐
相关产品推荐

