0
 #include <sys/types.h>
 #include <stddef.h>
 #include <stdlib.h>
 #include <sys/wait.h>
 #include <signal.h>
 #include <iostream>
 #include <unistd.h>
 int main(){


        signal(SIGCHLD,SIG_IGN );
        pid_t pid  = vfork();
        if(pid <0){
            std::cout<< "Error: Fork failed at main!!!";
            exit(1);
        }else if (0 == pid){


            char * cmd[] ={(char*)"../work/C++11/Prj_LargeFile/script/Logger.pl",NULL};
            //char * cmd[] = {(char*)"pwd",NULL};
            //char * cmd[] = {(char*)"/usr/bin/perl",(char*)"../work/C++11/Prj_LargeFile/script/Logger.pl",NULL};

            execvp(cmd[0],cmd);


             _exit(0);
        }
}

我希望有一个孤立的子进程,它将在后台运行一个 perl 脚本,并且我希望父进程在不等待其子进程的情况下完成。因此,我在开始时使用了 signal(SIGCHLD,SIG_IGN) 来忽略完成时的子信号并避免僵尸。但是当我运行代码时,它给我的错误是不能忽略信号 CHLD,强制默认。. 另一方面,当我运行那些注释行而不是运行所需的信号时。这是什么原因?

4

1 回答 1

2

Perl 发出这个警告。就 Perl 而言,看起来最近版本的 glibc(或者可能是 Linux 内核中的特定选项)已经删除了忽略 SIGCHLD 的能力。我不知道为什么会这样,但我只是在以前乐于忽略 SIGCHLD 的系统上遇到它。

根据perldoc perlipc,您绝对应该查看更多信息,解决此问题的最佳方法是:

use POSIX ":sys_wait_h"; # for nonblocking read
$SIG{CHLD} = sub {
    while ((my $child = waitpid(-1, WNOHANG)) > 0) {
        # $Kid_Status{$child} = $?;
    }
};
# do something that forks...

$Kid_Status来自原始 perldoc,但我将其注释掉,因为其目的是忽略子进程,并且我想明确表示内部while不需要包含任何代码。有多种方法可以处理 perldoc 中的子进程,例如,如果您的 Perl 脚本打算进行守护进程,或者您打算在处理程序中execdie在处理程序中进行处理。

如果您无法编辑您正在调用的 Perl 脚本,那么我建议在告诉用户忽略虚假警告STDERR之前打印一行。execvp例如,

fputs("The next line is a harmless warning.\n", stderr);
于 2018-04-13T20:12:24.037 回答