Rhandom has asked for the wisdom of the Perl Monks concerning the following question:

On my server (Linux 2.2.16 - Perl 5.005_03) the select command aborts whenever a SIG (that I have caught) is sent to the running process. For example, if I do:

#!/usr/bin/perl $SIG{CHLD} = sub{ print "Got $_[0]\n"; }; print $$,"\n"; select(undef,undef,undef,10000); print "all done\n";'


And then do a kill -CHLD <pid>, the select doesn't continue. I am sure that there might be a flag that I can set that will let this continue with the rest of the timeout that it had. However, I love the fact that it shortcuts the timeout -- this opens up many posibilities and simplifies life quite a bit -- it maybe even help to write a SIG safe system on old perls.

I am mostly wondering if this is consistent across platforms (Solaris, BSD, Linux, OSX, Windows, etc).

my @a=qw(brilliant braindead); print $a[rand(@a)];

Replies are listed 'Best First'.
Re: select and %SIG
by tadman (Prior) on Aug 04, 2001 at 08:22 UTC
    I'm pretty sure because of the way signals are implemented on most UNIX-type platforms that this should be the behavior you would expect. Windows is another story, and I'm not sure what to expect. POSIX support is always a bit strange under Windows.

    A probable explanation is that the 'select' function is unlike most functions in that it involves a kernel call that puts the process into a suspended state, as the process is not actually "running" while the select call is waiting. This is unlike, say, a for(;;) loop which will use 100% of CPU, though achieving the same sort of delay effect.

    It would stand to reason that the kernel call is aborted prematurely and the appropriate signal handler is called. Any similar kernel call should also be interrupted by a signal as well, such as the sleep function.
Re: select and %SIG
by bschmer (Friar) on Aug 04, 2001 at 18:12 UTC
    It's actually quite easy to "continue" the select after receiving a signal, just put the select in a loop like this:
    my $timeleft = 10000; while ($timeleft){ $timeleft = (select(undef,undef,undef,$timeleft))[1]; }
    This works on Linux and should work on other UNIX-like OSs as well. It won't work on Windows (both ActiveState and Cygwin) since select returns the time that was passed in as $timeleft, regardless of how long you've slept.

    Hope this helps.