代码之家  ›  专栏  ›  技术社区  ›  Chris Simmons

在Solaris 9上睡眠时发出SIGALRM

  •  3
  • Chris Simmons  · 技术社区  · 17 年前

    在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=>未定义”,这是预期的-非chrooted环境具有相同的行为。但是,如果我将脚本更改为包括:

    $SIG{ALRM} = sub {};
    

    ... 一切正常。那么,怎么回事?我对Solaris没有太多经验,但必须有一种方法使默认信号处理程序正常工作。

    3 回复  |  直到 17 年前
        1
  •  9
  •   pilcrow    17 年前

    我建议只需更换 sleep 1 select(undef, undef, undef, 1)

    根据您给出的症状,我敢打赌您的chroot perl脚本正在实现 sleep 依据 SIGALRM (正如POSIX所允许的),由于某种原因,perl并没有捕获到它应该捕获的信号,可能是因为它不期望实现。这是您定制的perl版本吗?这是一种特殊的习惯吗 libc ? 做 perl -e "sleep 1" 桁架 .

    select 不会弄脏你的 西格尔姆 .

        2
  •  3
  •   Kenster marc_s    17 年前

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

    truss testprogram.pl
    

    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
    

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

        3
  •  1
  •   Chas. Owens    17 年前

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

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

    推荐文章
    Selena Gomez  ·  汇编算法
    12 年前