exec后信号SIGCHLD未被设置为SIG_IGN,尽管之前是SIG_IGN

0 投票
1 回答
998 浏览
提问于 2025-04-18 09:14

这是我的程序 popen_test.cpp

int main(int argc, char* argv[])
{
    signal(SIGCHLD, SIG_IGN);
    sigset_t sset;
    sigaddset(&sset, SIGCHLD);
    sigprocmask(SIG_UNBLOCK, &sset, &sset);
    char command[128] = {0};
    snprintf(command, sizeof(command), "python popen_test.py");
    FILE* file;
    file = popen(command, "r");
    if ( !file )
    {     
        printf("command: %s is error\n", command);
        return -1;
    } 
    char result[256]={0};
    int len = fread(result, sizeof(char), 256, file);
    printf("result is :%s\n", result); 
    int ret = pclose(file);
    if (ret == -1)
    {
        printf("pclose error:%d, errno:%d, str_err:%s\n", ret, errno, strerror(errno));
        return -1; 
    }

}

脚本是

import os
import signal
import subprocess

if __name__ == "__main__":
    test = signal.getsignal(signal.SIGCHLD)
    if test == signal.SIG_DFL:
        print "sig_dfl"
    if test == signal.SIG_IGN:
        print "sig_ign"
    print test

POPEN 会创建一个子进程;这个子进程会调用 exec 来运行 python popen_test.py。我知道当调用 exec 时,SIGCHLD 信号(如果设置为 SIG_IGN)可能会被重置为 SIG_DFL,但为什么结果是 sig_dfl,而不是 sig_ign 呢?

1 个回答

0

你没有遵循对 sigprocmask() 函数参数的限制。你的编译器应该会对你重复使用同一个参数发出警告。


关于 execv() 函数,POSIX 规范中有这样的说明:

在调用进程中设置为默认动作(SIG_DFL)的信号,在新进程中也应该设置为默认动作。除了 SIGCHLD 之外,调用进程中设置为忽略(SIG_IGN)的信号,在新进程中也应该设置为忽略。

如果调用进程中将 SIGCHLD 信号设置为忽略,那么在新进程中该信号是被忽略还是恢复为默认动作就不确定了。

这位 提问者 评论道:

但是《UNIX环境高级编程》说如果调用进程中将 SIGXXX 信号设置为忽略,那么在新进程中该信号也应该被忽略?

这里的区别在于,APUE 讨论的是 UNIX,而 UNIX 并不完全等同于 POSIX(虽然两者很接近)。POSIX 规定一个平台可以符合 POSIX 标准,但仍然可以将 SIGCHLD 重置为 SIG_DFL,即使在原始进程中它是 SIG_IGN。你的代码似乎表明你的平台就是 POSIX 为什么对 SIGCHLD 有这个例外的原因。

顺便问一下,你使用的是哪个平台?

撰写回答