You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

父进程接收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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 12:48:15