在 Solaris 9 上休眠时发出 SIGALRM

发布于 2024-07-26 08:42:30 字数 644 浏览 6 评论 0原文

我在 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',这是预期的 - 非 chroot 环境具有相同的行为。 但是,如果我更改脚本以包括:

$SIG{ALRM} = sub {};

...一切正常。 那么,到底是怎么回事呢? 我对 Solaris 没有太多经验,但必须有一种方法可以使默认信号处理程序正常运行。

I'm running into a bit of a weird error while running Perl in a chroot environment on Solaris 9 (Sparc). We are using a custom Perl, but it's almost exactly Perl 5.8.7, and this version has been running for years on various platforms including Solaris 8-10.

The following code is pretty straightforward:

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

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

However, if I run that, "Just woke up!" never gets printed - instead, the program ends and "Alarm Clock" is echoed to the screen. This only happens if there's a sleep - if I write a program that does a lot of math and takes 10 seconds to run, everything works fine. It also only happens in a chroot environment.

I've dumped %SIG, which has an entry of 'ALRM => undef', which is expected - the non-chrooted environment has the same behaviour. However, if I change the script to include:

$SIG{ALRM} = sub {};

... everything works just fine. So, what's the deal? I don't have a lot of experience with Solaris, but there's got to be a way to make the default signal handlers behave properly.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

你不是我要的菜∠ 2024-08-02 08:42:30

我建议简单地将 sleep 1 调用替换为 select(undef, undef, undef, 1) 并避免整个问题。

从您给出的症状来看,我敢打赌您的 chroot'd perl 脚本正在根据 SIGALRM 实现 sleep (POSIX 允许),并且对于某些原因 perl 没有捕获该信号,因为它应该,也许是因为它不期望该实现。 这是你定制的 Perl 版本吗? 这是 chroot 后的 libc 中的一个特性吗? chroot 下的 perl -e "sleep 1" 是否显示同样的问题? 等等。如果没有环境和像 truss 这样的工具,很难说。

同样,整个问题是可以避免的:select 不会与 SIGALRM 混在一起。

I recommend simply replacing the sleep 1 calls with select(undef, undef, undef, 1) and avoiding the whole issue.

From the symptoms you give, I'd wager that your chroot'd perl script is implementing sleep in terms of SIGALRM (as is permitted by POSIX), and that for some reason perl is not catching that signal as it should, perhaps because it isn't expecting that implementation. Is it your custom build of perl? Is it an idiosyncrasy in the chroot'd libc? Does perl -e "sleep 1" under chroot show the same problem? Etc. Etc. Hard to say without access to the environment and a tool like truss.

Again, the whole issue can be avoided: select won't muck with SIGALRM.

音栖息无 2024-08-02 08:42:30

我尝试的第一件事是在 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 正在加载哪些共享库。

The first thing I'd try is to run your sample program under truss:

truss testprogram.pl

This will show the actual system calls used to implement the sleep. On a Solaris 8 system that I have access to, the relevant part of the output is:

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

On a Solaris 10 host, it outputs:

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

I imagine you'll get something closer to the Solaris 8 output, and it'll probably show the sigaction() call fail for some reason.

Beyond that, I'd check that the shared libraries within the chroot /usr/lib are actually the correct versions for the host and OS version. The truss output will also show you exactly which shared libraries are being loaded by perl.

他是夢罘是命 2024-08-02 08:42:30

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

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

Do you still have the version of Perl that comes with Solaris? If so, then try your code on it. If you don't have that version, then I suggest downloading Perl 5.8.7, compiling a stock version, and then testing your script on it.

If your script runs correctly, on either of those two versions, then you know the problem is related to the changes in your version of Perl. If the script has the same error, then then I would suggest downloading Perl 5.8.9, compiling it, and then checking to see if the bug goes away. If it doesn't, then, congratulations, you have found a bug in Perl. You will probably want to run perlbug to report it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文