执行后,信号SIGCHLD不再是SIG_IGN,即使它之前是SIG_IGN

After an exec, signal SIGCHLD is not SIG_IGN even though it was SIG_IGN before

本文关键字:IGN SIG 不再 信号 执行 SIGCHLD      更新时间:2023-10-16

这是我的程序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 errorn", command);
        return -1;
    } 
    char result[256]={0};
    int len = fread(result, sizeof(char), 256, file);
    printf("result is :%sn", result); 
    int ret = pclose(file);
    if (ret == -1)
    {
        printf("pclose error:%d, errno:%d, str_err:%sn", 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_sign ?

您没有尊重sigprocmask()参数上的限制限定符。你的编译器应该抱怨使用相同的参数两次。


execv()文档的POSIX规范:

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

如果SIGCHLD信号被设置为被调用进程映像忽略,则未指定SIGCHLD信号是被设置为被忽略还是被设置为新进程映像中的默认动作。

OP评论:

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

区别在于APUE处理的是UNIX;UNIX实际上不是POSIX(尽管两者很接近)。POSIX表示平台可以与POSIX兼容,并且仍然将SIGCHLD重置为SIG_DFL,即使它在原始进程中是SIG_IGN。你的代码似乎证明了你的平台是POSIX为SIGCHLD提供豁免的原因。

出于好奇,请问您使用的是哪个平台?