Search code examples
perlsolarissignalssparc

SIGALRM while sleeping on Solaris 9


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.


Solution

  • 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.