tags:

views:

233

answers:

3

If I tell Perl to explicitly ignore a signal, SIGINT has no effect:

$SIG{INT} = 'IGNORE';
my $count = 0;
say $count++ and sleep 1 while 1;

Then pressing Control-C, rather obviously, has no effect. If, on the other hand, I tell it to do nothing:

$SIG{INT} = sub { };
my $count = 0;
say $count++ and sleep 1 while 1;

Then pressing Control-C has an effect! It wakes up the program from its sleep() call and immediately increments the count. What's the difference between ignoring a signal and telling it to do nothing?

In my program, I'd like to have code run on SIGINT, without having it disrupt anything. I want something like:

$SIG{INT} = sub { say "Caught SIGINT!"; return IGNORED; };  # runs without disrupting sleep
A: 

Not sure why it is not working as you expect, but normally when I try to accomplish similar things I also trap the TERM signal in addition to the INT signal.

Marius Kjeldahl
+10  A: 

What's the difference between ignoring a signal and telling it to do nothing?

Your "do nothing" handler is still invoked when the signal is delivered, interrupting the sleep call in this case. Ignored signals, on the other hand, are simply discarded by the system, having no effect whatsoever on the process.

See here for a C-specific but more comprehensive reference.

pilcrow
+4  A: 

Lots of system calls can be interrupted by signal delivery. Usually you can check $! (aka errno) to see if it is EINTR and take action to re-try the failed system-call.

If its important to you that certain sections of your code (in this case, your call to sleep()) are not interrupted, then you can use POSIX::sigprocmask to block signals while you're in your critical section. Any signals received by the application will be queued up until you unblock them, at which point they'll be delivered. I'm pretty sure there are some funny semantics when multiple signals of a particular type are blocked (I think they may coalesce into a single signal).

Here's a nice primer from IBM on re-entrant functions, and includes a little sample with sigprocmask.

Peter Kovacs
+1. My understanding is that most UNIX variants will absolutely coalesce multiple signals of the same type. So when you see a signal XYZ, all you can be certain of is that XYZ was raised *at least once*.
j_random_hacker