繁体   English   中英

如果孩子发出信号,Perl从fork / exec检测到错误的退出代码

[英]Perl detects wrong exit code from fork/exec if child signalled

我从perl中派生/执行了一个C ++程序,并想检测子项的退出状态(尤其是当子项由于段错误而退出时)

perl的行为是不一致的,具体取决于孩子是否调用exit() ,是从外部发出信号还是实际上遇到了段错误。

从外壳程序来看,C ++的退出代码始终正确。 例如。 echo $? 匹配程序所做的。

在perl中,仅当调用exit()时,perl检测到的退出代码才是正确的。 如果程序由于信号或段错误而退出,则perl检测到的退出代码始终为0。

为什么?

我想在perl脚本中始终获得C ++程序的退出代码。

perl 5.10.1,Centos 6 32位,g ++ 4.8.2

检测结果

  • 实际的段错误(启用了动boom ): Perl Complete: 27322 exited (exit 0, sig 11, core 0)
  • a.out通过kill -11 <pid>Perl Complete: 27248 exited (exit 0, sig 11, core 0)
  • a.out完成,调用exit(139)Perl Complete: 27237 exited (exit 139, sig 0, core 0)

在上述三种情况下,从外壳程序调用a.out始终会显示正确的退出代码。

C ++ A.OUT

(根据测试注释动boom

#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <stdlib.h>

int
main(int argc, char  **argv)
{
    printf("Started with PID %d\n", getpid());

    int d = 1;
    if (argc > 1)
        d = atoi(argv[1]);

    int loops = 10;
    while(loops-- > 0)
    {
        printf("Ping\n");
        sleep(1);
    }

    printf("MAKE SEGFAULT\n");
    int boom = *(int*)0x00;

    printf("exit with %d\n", d);
    exit(d);
}

PERL

#!/usr/bin/perl

use POSIX ":sys_wait_h";

my $fullprocname = "./a.out 139";
my $childPID = fork();

if ($childPID == 0)        # child
{
    open(STDERR, ">&SAVEERR");  # restore stderr
    $< = $>;                    # set real to effective uid, otherwise
                                # some env variables not passed in ??
    exec ($fullprocname) or die "exec $fullprocname failed: $!\n"; 
}
else                       # parent
{
    print("DVMon.pl: Forked $childPID for $fullprocname\n");
}

print("Waiting for child process\n");
my $child = wait();

my $exitStatus = $? >> 8;   # similar to WEXITSTATUS
my $termSig    = $? & 127;  # similar to WTERMSIG
my $coreDump   = $? & 128;  # similar to WCOREDUMP

my $msg = "$childPID exited (exit $exitStatus, sig $termSig, core $coreDump)";
print("Perl Complete: $msg\n");

这是按设计工作。 在shell中,有两种方法可以从命令中获取139的退出代码。

  1. 该命令使系统调用exit(139)
  2. 该命令以信号11终止

但是POSIX-y系统可以区分这两个事件,Perl可以通过这些方法来使其$? 该变量比shell提供的内容更具信息性。

如果程序由于信号或段错误而退出,则perl检测到的退出代码始终为0。为什么?

它从未到达exit ,因此WEXITSTATUS是没有意义的,因此系统将其设置为零。

Perl显示的值是系统提供的值,它们是应该期望的值。 例如,在C语言中您将获得与在Perl中相同的结果。

当进程被信号杀死时,系统将提供该信息。 另一方面, sh不提供该信息。 如果您想知道为什么sh$? 与Perl的$?不同$? ,这是因为外壳程序将退出代码分成8位,如下所示:

 $?<sh> = ( $?<real> & 0x7F ) ? ( $?<real> | 0x80 ) : ( $?<real> >> 8 );

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM