我从 perl fork /执行一个 C++ 程序,并希望检测子程序的退出状态(特别是当子程序由于段错误而退出时)
根据子进程是否调用 exit()
,perl 行为会不一致。 ,从外部发出信号,或者实际上遇到了段错误。
从 shell 中,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
在上述所有三种情况下,从 shell 始终显示正确的退出代码。
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)
- 命令以信号 11 终止
但是 POSIX-y 系统可以区分这两个事件,并且 Perl Hook 这些方法以使其 $?
变量比 shell 提供的信息更丰富。
关于c++ - 如果子进程发出信号,Perl 会检测到 fork/exec 的错误退出代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45610409/