SIGALRM在Solaris 9上睡觉时

时间:2009-07-06 02:47:26

标签: perl solaris signals sparc

在Solaris 9(Sparc)的chroot环境中运行Perl时,我遇到了一些奇怪的错误。我们 使用自定义Perl,但它几乎完全是Perl 5.8.7,并且这个版本已经在包括Solaris 8-10在内的各种平台上运行多年。

以下代码非常简单:

#!/usr/bin/perl
use strict; 
use warnings;

print "About to sleep(1)\n";
sleep 1;
print "Just woke up!\n";

然而,如果我跑了,“刚刚醒来!”从不打印 - 相反,程序结束,“闹钟”响应屏幕。只有在睡眠时才会发生这种情况 - 如果我编写的程序执行大量数学操作并需要10秒钟才能运行,那么一切正常。它也只发生在chroot环境中。

我转储了%SIG,其条目为'ALRM => undef',这是预期的 - 非chrooted环境具有相同的行为。但是,如果我将脚本更改为包括:

$SIG{ALRM} = sub {};

......一切正常。那么,这笔交易是什么?我没有很多使用Solaris的经验,但必须有一种方法可以使默认的信号处理程序正常运行。

3 个答案:

答案 0 :(得分:9)

我建议只使用sleep 1替换select(undef, undef, undef, 1)来电并避免整个问题。

根据你给出的症状,我打赌你的chroot perl脚本正在sleep实现SIGALRM(由POSIX允许),并且由于某种原因perl是没有抓住那个应该发出的信号,也许是因为它不期待这种实施。它是你自定义构建的perl吗?这是chroot'd libc中的特质吗? chroot下的perl -e "sleep 1"是否显示同样的问题?等等。很难说无法访问环境和像 truss 这样的工具。

同样,可以避免整个问题:select不会与SIGALRM混淆。

答案 1 :(得分:3)

我要尝试的第一件事是在truss下运行你的示例程序:

truss testprogram.pl

这将显示用于实现睡眠的实际系统调用。在我有权访问的Solaris 8系统上,输出的相关部分是:

write(1, " A b o u t   t o   s l e".., 18)      = 18
time()                                          = 1247258429
alarm(0)                                        = 0
sigaction(SIGALRM, 0xFFBEF6E0, 0xFFBEF790)      = 0
sigfillset(0xFF0C28D0)                          = 0
sigprocmask(SIG_BLOCK, 0xFFBEF780, 0xFFBEF770)  = 0
alarm(1)                                        = 0
    Received signal #14, SIGALRM, in sigsuspend() [caught]
sigsuspend(0xFFBEF760)                          Err#4 EINTR
setcontext(0xFFBEF448)
alarm(0)                                        = 0
sigprocmask(SIG_UNBLOCK, 0xFFBEF780, 0x00000000) = 0
sigaction(SIGALRM, 0xFFBEF6E0, 0x00000000)      = 0
time()                                          = 1247258430
Just woke up!
write(1, " J u s t   w o k e   u p".., 14)      = 14

在Solaris 10主机上,它输出:

write(1, " A b o u t   t o   s l e".., 18)      = 18
time()                                          = 1247258270
nanosleep(0xFFBFF770, 0xFFBFF768)               = 0
time()                                          = 1247258271
Just woke up!
write(1, " J u s t   w o k e   u p".., 14)      = 14

我想你会更接近Solaris 8输出,并且它可能会因某种原因显示sigaction()调用失败。

除此之外,我还要检查chroot / usr / lib中的共享库实际上是主机和操作系统版本的正确版本。 truss输出还将显示perl正在加载哪些共享库。

答案 2 :(得分:1)

您是否还拥有Solaris附带的Perl版本?如果是这样,那么尝试你的代码。如果您没有该版本,那么我建议下载Perl 5.8.7,编译股票版本,然后在其上测试您的脚本。

如果您的脚本在这两个版本中的任何一个上正确运行,那么您就知道该问题与您的Perl版本中的更改有关。如果脚本有相同的错误,那么我建议下载Perl 5.8.9,编译它,然后检查bug是否消失。如果没有,那么,恭喜,您在Perl中发现了一个错误。您可能希望运行perlbug进行举报。