如何调试突然退出的Perl程序?

时间:2010-06-09 06:11:04

标签: perl debugging

我有基于IO::Async的Perl程序,它有时会在几小时/几天后退出而不会打印任何错误消息。 dmesg/var/log中也没有任何内容。 STDOUT / STDERR都是autoflush(1),因此不应在缓冲区中丢失数据。它实际上并没有从IO::Async::Loop->loop_forever退出 - 我把它放在那里只是为了确保它永远不会被触发。

现在一种方法是继续使用越来越多的打印方式来加工程序,并希望其中一个给我一些线索。有没有更好的方法来获取信息,使程序退出/静默崩溃?

3 个答案:

答案 0 :(得分:6)

我使用的一个技巧是在straceltrace下运行程序(或使用strace附加到流程)。当然,这是在Linux下。在其他操作系统下,您可以使用ktracedtrace或任何适当的操作系统。

我用过的程序只能在几天或一周内出现稀疏问题然后只有数百个系统中的少数几个系统将我的跟踪器的输出定向到FIFO,并且自定义程序只保留10K行在一个环形缓冲区(并在SIGPIPE和SIGHUP上使用一个处理程序将当前缓冲区内容转储到一个文件中。(这是一个简单的程序,但我没有方便的副本,今晚我不打算重写它) ;我的副本是为内部使用而写的,由前雇主拥有。)

环形缓冲区允许程序无限期运行,因为担心系统会在磁盘空间中运行......在这些问题上我们通常只需要几百甚至几千行跟踪。

答案 1 :(得分:3)

如果您正在捕获STDERR,则可以将该程序作为perl -MCarp::Always foo_prog启动。 Carp::Always强制对所有错误进行堆栈跟踪。

答案 2 :(得分:0)

突然退出而没有任何错误消息可能是SIGPIPE。传统上SIGPIPE用于停止以下管道中的cat命令:

cat file | head -10

它通常不会导致libcperl打印任何内容,以表明发生了什么。

因为在基于IO::Async的程序中你不想默默地退出SIGPIPE,我的建议是将程序的主文件中的某处放在类似

$SIG{PIPE} = sub { die "Aborting on SIGPIPE\n" };

至少会提醒你这个事实。如果您使用Carp::croak而不使用\n,您甚至可能会幸运地获得导致syswrite的{​​{1}}等文件/行号。