簡體   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