Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux Perl 5.8:当使用SIGCHLD时,可以从backticks获取任何返回代码_Linux_Perl - Fatal编程技术网

Linux Perl 5.8:当使用SIGCHLD时,可以从backticks获取任何返回代码

Linux Perl 5.8:当使用SIGCHLD时,可以从backticks获取任何返回代码,linux,perl,Linux,Perl,在Perl中使用CHLD信号处理程序时,即使使用system和backticks,也会发送CHLD信号。但是对于系统和backticks子进程,wait和waitpid似乎都没有设置$?在SuSE 11 linux上的信号处理程序中。当CHLD信号处理程序处于活动状态时,是否有任何方法确定backtick命令的返回代码 我为什么要这个?因为我想fork(?)并启动一个中等长度的命令,然后调用一个需要很长时间才能生成答案的perl包(该包使用反勾号执行外部命令,并检查它们的返回代码(单位为$?),

在Perl中使用CHLD信号处理程序时,即使使用system和backticks,也会发送CHLD信号。但是对于系统和backticks子进程,wait和waitpid似乎都没有设置$?在SuSE 11 linux上的信号处理程序中。当CHLD信号处理程序处于活动状态时,是否有任何方法确定backtick命令的返回代码

我为什么要这个?因为我想fork(?)并启动一个中等长度的命令,然后调用一个需要很长时间才能生成答案的perl包(该包使用反勾号执行外部命令,并检查它们的返回代码(单位为$?),并且知道我的命令何时完成,以便我可以采取行动,例如启动第二个命令。(关于如何在不使用SIGCHLD的情况下实现这一点的建议也很受欢迎。)但是既然信号处理程序销毁backtick$?值,则该包失败

例如:

use warnings;
use strict;
use POSIX ":sys_wait_h";

sub reaper {
    my $signame = shift @_;
    while (1) {
       my $pid = waitpid(-1, WNOHANG);
       last if $pid <= 0;
       my $rc = $?;
       print "wait()=$pid, rc=$rc\n";
    }
}

$SIG{CHLD} = \&reaper;

# system can be made to work by not using $?, instead using system return value
my $rc = system("echo hello 1");
print "hello \$?=$?\n";
print "hello rc=$rc\n";

# But backticks, for when you need the output, cannot be made to work??
my @IO = `echo hello 2`;
print "hello \$?=$?\n";

exit 0;

所以我找不到任何地方可以访问backticks返回值。

同样的问题已经困扰了我好几天了。我相信有两个解决方案需要取决于你有你的背勾

如果您在子代码中有反勾号:


解决办法是把下面的线放在儿童叉子里面。我认为您上面的陈述“如果我完全关闭了背景信号周围的CHLD处理程序,那么如果孩子结束了,我可能无法得到信号”是不正确的。当子级退出时,您仍将在父级中获得回调,因为该信号仅在子级内部被禁用。因此,当子进程退出时,父进程仍然会收到一个信号。只是当孩子的孩子(backticks中的部分)退出时,孩子没有收到信号

local$SIG{'CHLD'}='DEFAULT'

我不是Perl专家,我已经读到应该将CHLD信号设置为字符串'IGNORE',但这在我的情况下不起作用。从表面上看,我相信这可能是造成问题的原因。完全忽略这一点似乎也解决了问题,我想这与将其设置为默认值是一样的

如果父代码中有反勾号:

将此行添加到收割机功能:
local($!,$?)


正在发生的事情是,当backticks中的代码完成并且收割器设置为$?,正在调用收割器?。通过赚美元?local它不设置全局$?。

因此,基于MikeKull的答案,下面是一个工作示例,其中fork的子级使用backticks,但仍然获得正确的返回代码。这个例子更好地描述了我正在做的事情,而原来的例子没有使用forks,也无法表达整个问题

use warnings;
use strict;
use POSIX ":sys_wait_h";

# simple child which returns code 5
open F, ">", "exit5.sh" or die "$!";
print F<<EOF;
#!/bin/bash
echo exit5 pid=\$\$
exit 5
EOF
close F;

sub reaper
{
    my $signame = shift @_;
    while (1)
    {
        my $pid = waitpid(-1, WNOHANG);
        print "no child waiting\n" if $pid < 0;
        last if $pid <= 0;
        my $rc = $? >> 8;
        print "wait()=$pid, rc=$rc\n";
    }
}

$SIG{CHLD} = \&reaper;

if (!fork)
{
    print "child pid=$$\n";
  { local $SIG{CHLD} = 'DEFAULT'; print `./exit5.sh`; }
    print "\$?=" . ($? >> 8) . "\n";
    exit 3;
}

# sig CHLD will interrupt sleep, so do multiple
sleep 2;sleep 2;sleep 2;

exit 0;

因此,在调用子对象之前,当父对象的收割机被禁用时,子对象中接收到预期的返回代码5,但如ikegami所示,当子对象退出时,父对象仍会收到CHLD信号和正确的返回代码。

Backticks等待其子对象退出。在反标记期间,您应该将SIGCHLD处理程序置于挂起状态。如果我在反标记(实际上是一个单独的包)周围完全关闭了CHLD处理程序,则如果子项在禁用时结束,则可能无法获得该信号。您将在取消屏蔽时获得该信号。或者如果没有,您可以在取消屏蔽时无条件调用信号处理程序。另一种解决方案是在另一个子系统中的父系统中运行您当前运行的代码。谢谢,我想我会继续执行双叉建议!注意它是$SIG{CHLD},而不是$SIG{CHLD},并且$SIG{CHLD}='IGNORE';谢谢,我已经更新了我的答案,并将其更改为默认值,因为我认为这与将其设置为undef相同,但undef在5.8中似乎不起作用
use warnings;
use strict;
use POSIX ":sys_wait_h";

# simple child which returns code 5
open F, ">", "exit5.sh" or die "$!";
print F<<EOF;
#!/bin/bash
echo exit5 pid=\$\$
exit 5
EOF
close F;

sub reaper
{
    my $signame = shift @_;
    while (1)
    {
        my $pid = waitpid(-1, WNOHANG);
        print "no child waiting\n" if $pid < 0;
        last if $pid <= 0;
        my $rc = $? >> 8;
        print "wait()=$pid, rc=$rc\n";
    }
}

$SIG{CHLD} = \&reaper;

if (!fork)
{
    print "child pid=$$\n";
  { local $SIG{CHLD} = 'DEFAULT'; print `./exit5.sh`; }
    print "\$?=" . ($? >> 8) . "\n";
    exit 3;
}

# sig CHLD will interrupt sleep, so do multiple
sleep 2;sleep 2;sleep 2;

exit 0;
child pid=32307
exit5 pid=32308
$?=5
wait()=32307, rc=3
no child waiting