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

时间:2017-08-10 09:56:32

标签: c++ linux perl

我从perl派生/执行一个C ++程序,想要检测孩子的退出状态(特别是当孩子因为段错误退出时)

perl行为不一致取决于孩子是否呼叫exit(),是否在外部发出信号,或实际遇到段错误。

从shell中,C ++的退出代码始终是正确的。例如。 echo $?与程序的作用相符。

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

为什么?

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

perl 5.10.1,Centos 6 32-bit,g ++ 4.8.2

测试结果

  • 实际Segfault(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)

从shell中调用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");

1 个答案:

答案 0 :(得分:1)

  

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

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

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

当一个进程被信号杀死时,系统会提供该信息。另一方面,sh不提供该信息。如果您想知道为什么sh的{​​{1}}与Perl的$?不同,那是因为shell将退出代码变为8位,如下所示:

$?