[英]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)
kill -11 <pid>
: Perl Complete: 27248 exited (exit 0, sig 11, core 0)
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的退出代码。
exit(139)
但是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.