Perl 系统调用导致核心转储,但 $?保持为零
我有一个 Perl 脚本(在 VirtualBox 内的 Xubuntu Lucid Lynx 上运行),它包装了多个 C/C++ 二进制文件,将其中一个的输入输入到另一个中。其中一行通常包含:
my $ret_code=`cat $input | c_binary`;
my $ret_val= $?;
对于某些输入文件,代码会导致 coredump,但 $ret_val
和 $ret_code
分别为 0 和 ""。当我运行它时,我可以看到错误滚动,但我似乎无法以编程方式“捕获”这个错误。 我该怎么做? 目的是在出错时从输入中删除一些行并重试解析。
以下是错误:
*** stack smashing detected ***: code/parser terminated
======= Backtrace: =========
/lib/tls/i686/cmov/libc.so.6(__fortify_fail+0x50)[0x798390]
/lib/tls/i686/cmov/libc.so.6(+0xe233a)[0x79833a]
code/parser[0x804edd8]
[0x2e303039]
======= Memory map: ========
0043b000-0043c000 r-xp 00000000 00:00 0 [vdso]
0045a000-00475000 r-xp 00000000 08:01 11041 /lib/ld-2.11.1.so
00475000-00476000 r--p 0001a000 08:01 11041 /lib/ld-2.11.1.so
00476000-00477000 rw-p 0001b000 08:01 11041 /lib/ld-2.11.1.so
006b6000-00809000 r-xp 00000000 08:01 10897 /lib/tls/i686/cmov/libc-2.11.1.so
00809000-0080a000 ---p 00153000 08:01 10897 /lib/tls/i686/cmov/libc-2.11.1.so
0080a000-0080c000 r--p 00153000 08:01 10897 /lib/tls/i686/cmov/libc-2.11.1.so
0080c000-0080d000 rw-p 00155000 08:01 10897 /lib/tls/i686/cmov/libc-2.11.1.so
0080d000-00810000 rw-p 00000000 00:00 0
008ba000-008d7000 r-xp 00000000 08:01 8268 /lib/libgcc_s.so.1
008d7000-008d8000 r--p 0001c000 08:01 8268 /lib/libgcc_s.so.1
008d8000-008d9000 rw-p 0001d000 08:01 8268 /lib/libgcc_s.so.1
00c89000-00cad000 r-xp 00000000 08:01 10901 /lib/tls/i686/cmov/libm-2.11.1.so
00cad000-00cae000 r--p 00023000 08:01 10901 /lib/tls/i686/cmov/libm-2.11.1.so
00cae000-00caf000 rw-p 00024000 08:01 10901 /lib/tls/i686/cmov/libm-2.11.1.so
08048000-08055000 r-xp 00000000 08:01 407893 /home/abugorsk/Documents/code/stepbystep/collins-parser/code/parser
08055000-08056000 r--p 0000c000 08:01 407893 /home/abugorsk/Documents/code/stepbystep/collins-parser/code/parser
08056000-08057000 rw-p 0000d000 08:01 407893 /home/abugorsk/Documents/code/stepbystep/collins-parser/code/parser
08057000-0c50f000 rw-p 00000000 00:00 0
0e168000-0fa57000 rw-p 00000000 00:00 0 [heap]
b44a3000-b77c9000 rw-p 00000000 00:00 0
b77da000-b77dc000 rw-p 00000000 00:00 0
bff2b000-bff40000 rw-p 00000000 00:00 0 [stack]
Aborted
返回的值是:
LOG: Parser return code: 0
LOG: Parser return value:
有问题的实际代码片段:
my $command = "cd $STEPBYSTEP_HOME/collins-parser; cat models/model$model_num/events | code/parser $src models/model$model_num/grammar 10000 1 1 1 1 1> $dest 2> $parse_log";
llog "Executing command: $command";
my $ret_code = $?;
llog "Parser return code: $ret_code";
my $ret_val = `$command`;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
首先,您显示的代码中有一些可疑之处:您在实际运行命令之前获取了
$?
的值。现在我将讨论我认为您要写的内容:在此之后,
$ret_code
包含整个 shell 命令的状态。这又是列表中最后一个命令的状态,它是一个管道cat ... |代码/解析器...
。根据 shell 的不同,这可能是管道中最后一个命令的状态,即 code/parser(ksh、zsh),或者始终为 0(大多数 shell,包括 ash、bash 和pdksh)。对于您的情况,有一个简单的修复方法,即摆脱
cat
的无用使用:如果您有一个有用的命令而不是
cat
,那么您最好的选择是完全放弃外壳。这还有其他一些小好处:少了一个需要掌握的工具;更容易移植到非 UNIX 系统;适用于包含 shell 元字符的文件名(这也可以通过系统地使用quotemeta
来实现)。这是这个想法的要点(未经测试);perldoc -f open
和perldoc perlipc
可能会有所帮助。First, there's something fishy in the code you show: you're getting the value of
$?
before actually running the command. I'll now discuss what I think you meant to write:After this,
$ret_code
contains the status of the whole shell command. This, in turn, is the status of the last command in the list, which is a pipelinecat ... | code/parser ...
. Depending on the shell, this may either be the status of the last command in the pipeline, i.e.,code/parser
(ksh, zsh), or always be 0 (most shells, including ash, bash and pdksh).In your case, there's a simple fix, which is to get rid of the useless use of
cat
:If you had a useful command instead of
cat
, your best option would be to dispense with the shell altogether. This also has other minor benefits: one less tool to master; easier to port to non-unix systems; works with file names containing shell metacharacters (this can also be achieved by systematic use ofquotemeta
). Here's the gist of the idea (untested);perldoc -f open
andperldoc perlipc
may help.首先,您的命令行中有一个无用的
cat
,可以轻松地通过重定向替换它。我会尝试将命令更改为类似以下内容
或者,如果您尝试最小化输入文件以查找导致崩溃的原因,我强烈建议使用 Delta,它可以有效地自动执行此操作
First, you've got a useless
cat
in your command line that could easily be replaced by a redirection.I'd try changing the command to something like the following
Alternately, if you're trying to minimize your input file to find whatever's causing the crash, I highly recommend using Delta, which automates this effectively
由于 CRT 正在中止程序(即它实际上并没有通过信号崩溃,CRT 看到了废弃的堆栈金丝雀并手动中止了进程),因此其返回值将为零。我认为你在这里能做的最好的事情就是:
这样 CRT 垃圾就会被捕获,并且你可以在 Perl 脚本中检测到它。
Since the CRT is aborting the program (i.e. it doesn't actually crash via a signal, the CRT saw the trashed stack canary and manually aborted the process), its return value will be zero. I think the best you can do here is:
so that the CRT gunk will be captured and you can detect it in the Perl script.
为您的
c_binary
编译这个简单的替代品和这个 Perl 程序来运行它的图像
我得到
所以如您所见,您需要使用
WIFSIGNALED
和WTERMSIG< /code> 来自
POSIX
模块,以编程方式检测c_binary
被信号杀死——不仅仅是退出状态本身:Compiling this simple stand-in for your
c_binary
and this Perl program to run its image
I get
So as you can see, you need to use
WIFSIGNALED
andWTERMSIG
from thePOSIX
module to detect programmatically thatc_binary
was killed by a signal—not just the exit status itself: