unless (kill 0, $pid) {
warn "$pid has gone away!";
}
Perhaps a little more interesting than sending signals is catching
signals. Why might you want to do this? Well, suppose you have a
program that creates files in /tmp, and you
normally delete those files at the end of the program. If someone
presses Control-C during the execution, that leaves trash in
/tmp, a very unpolite thing to do. To fix this,
create a signal handler that takes care of the cleanup:
my $temp_directory = "/tmp/myprog.$$"; # create files below here
mkdir $temp_directory, 0700 or die "Cannot create $temp_directory: $!";
sub clean_up {
unlink glob "$temp_directory/*";
rmdir $temp_directory;
}
sub my_int_handler {
&clean_up;
die "interrupted, exiting...\n";
}
$SIG{'INT'} = 'my_int_handler';
.
. # Time passes, the program runs, creates some temporary
. # files in the temp directory, maybe somone presses Control-C
.
# Now it's the end of normal execution
&clean_up;
If the subroutine returns rather than exiting, execution resumes
right where it was interrupted. This can be useful if the interrupt
needs to actually interrupt something rather than causing it to stop.
For example, suppose processing each line of a file takes a few
seconds, which is pretty slow, and you want to abort the overall
processing when an interrupt is processed, but not in the middle of
processing a line. Just set a flag in the interrupt procedure, and
check it at the end of each line's processing:
my $int_count;
sub my_int_handler { $int_count++ }
$SIG{'INT'} = 'my_int_handler';
...
$int_count = 0;
while (<SOMEFILE>) {
... some processing that takes a few seconds ...
if ($int_count) {
# interrupt was seen!
print "[processing interrupted...]\n";
last;
}
}
Now as each line is processed, the value of
$int_count will be 0 if no one
has pressed Control-C, and so the loop continues to the next item.
However, if an interrupt comes in, the interrupt handler increments
the $int_count flag, breaking out of the loop when
checked at the end.