各种$ SIG {CHLD}值之间有什么区别?

Tru*_*ood 7 unix perl signals signal-handling sigchld

这些设置有什么区别?

$SIG{CHLD} = 'IGNORE'  
$SIG{CHLD} = 'DEFAULT'  
$SIG{CHLD} = ''  
$SIG{CHLD} = undef
Run Code Online (Sandbox Code Playgroud)

根据"UNIX环境中的高级编程,第2版",图10.1 SIGCHLD的默认值是"忽略".

如果"忽略"意味着"SIG_IGN",那么任何孩子都不会成为僵尸,事实并非如此.

从那里开始并没有那么清楚:

如果进程专门将其处置设置为SIG_IGN,则调用进程的子进程将不会生成僵尸进程.请注意,这与其默认操作(SIG_DFL)不同,后者将忽略图10.1中的操作.相反,在终止时,将丢弃这些子进程的状态.

我很难知道各种值(或未定义的非值)的影响是什么.到目前为止,解决方案一直是旋转这些选择,直到我得到所需的行为,而我更确切地了解每个值如何定义信号的行为.

行为:子进程调用"system"或使用反引号创建另一个子进程,并且信号通常会被错误的(父)处理程序捕获.设置本地处理程序可以工作,但如果我希望来自祖母的信号什么都不做,我不明白哪个值最合适.

有人可以照亮我吗?

更新: 根据ikegami的反馈,我做了一些具体的测试.该行为至少部分是特定于平台的.

请考虑以下片段:

$SIG{CHLD} = sub {
    while( ( my $child = waitpid( -1, &WNOHANG ) ) > 0 ) {
        print "SIGNAL CHLD $child\n";
    }
};

my $pid = fork();

if( ! $pid ) {
    system( 'echo Grandchild PID = $$' );
    sleep 2;
    exit;
}

print "Child PID = $pid\n";
sleep 5;
Run Code Online (Sandbox Code Playgroud)

Solaris 10上的Perl 5.8.6将显示system()调用的PID的"SIGNAL CHLD"消息.做任何事情,即使是微不足道的

当地$ SIG {CHLD};

孩子会压制这些消息.

在我试过的每一种味道上,收割机都看不到孩子.

mob*_*mob 12

有两种方法可以避免创建僵尸进程:

  1. 明确设定 $SIG{CHLD}='IGNORE'
  2. 使用waitwaitpid调用明确地收集死去的孩子(这可以在SIGCHLD处理程序内完成,但不一定要这样)

设置$SIG{CHLD}='IGNORE'在操作系统级别捕获SIGCHLD,清除子进程,甚至不用发信号通知您的Perl程序.

任何其他设置,其中包括'DEFAULT',undef,"",sub {},'some_function_name_that_doesnt_even_exist'将导致信号被传递到Perl和孩子就不会被自动收获.

通过使用wait和自己获取进程waitpid,您可以获得其他信息,例如子进程的退出状态,以及(或多或少)子进程完成的顺序.If $SIG{CHLD}设置为'IGNORE',waitwaitpid始终返回-1并且不设置$?.

SIGCHLD,如果有的话,总是传递到催生子进程的过程中,所以我不认为你是正确的说,一个SIGCHLD从孙子的过程(从一个system子进程中调用)被夹在父进程.可能发生的事情是您的子进程从其父进程继承信号处理程序.

system和反引号将(在大多数系统上)生成一个SIGCHLD完成,并将$?使用命令的退出状态设置值.但是,Perl将获得这些子过程本身,你将无法捕捉到的进程ID system或拨打反引号与waitwaitpid.


ike*_*ami 10

%SIG.

$SIG{CHLD} = 'IGNORE'; 导致您的进程忽略SIGCHLD信号.

$SIG{CHLD} = 'DEFAULT';导致您的进程处理SIGCHLD信号,就像您没有弄乱$SIG{CHLD}或等效一样.根据kill(1),我的系统上的进程默认忽略SIGCHLD

$SIG{CHLD} = '';并且$SIG{CHLD} = undef;不是有效值.

至于收割,IGNORE系统会在退出后立即自动获取其SIGCHLD处理程序明确设置为的父项的子项.

$ perl -e'
   my $pid = fork;
   if (!$pid) { sleep(1); exit; }
   sleep(2);
   system "ps -o pid,stat,command $pid";
'
  PID STAT COMMAND
14667 ZN+  [perl] <defunct>

$ perl -e'
   $SIG{CHLD}="IGNORE";
   my $pid = fork;
   if (!$pid) { sleep(1); exit; }
   sleep(2);
   system "ps -o pid,stat,command $pid";
'
  PID STAT COMMAND

$
Run Code Online (Sandbox Code Playgroud)

  • `''和`undef`是有效值,它们是DWIM,``删除$ SIG {CHLD}`也是如此. (2认同)