broccoli
broccoli

Reputation: 4836

Trapping signals cleanly in Perl

I have a simple Perl script that simply prints a line of text to stdout. What I want to accomplish is that while this script runs, if I (or someone else) issues a signal to that process to stop, I want it to trap that signal and exit cleanly. The code I have looks like the following

#!/usr/bin/perl -w

$| = 1;
use sigtrap 'handler' => \&sigtrap, 'HUP', 'INT','ABRT','QUIT','TERM';
while(1){
 print "Working...\n";
 sleep(2);
}
sub sigtrap(){
 print "Caught a signal\n";
 exit(1);
}

While this works well when I actually hit ctrl-c from the command line, if I issue a

kill -9 <pid>

It just dies. How do I get it to execute something before exiting? My general idea is to use this framework to capture when this script dies on a server due to a server reboot for maintenance or failure.

Thanks much in advance

Upvotes: 6

Views: 5395

Answers (3)

Daniel Kamil Kozar
Daniel Kamil Kozar

Reputation: 19266

You're sending two very different signals to your process. Pressing Ctrl-C in console usually sends the process a TERMINT signal, which - judging by your code - is caught and serviced. kill -9, though, sends signal number 9 explicitly, which is called KILL. This is one of the signals whose servicing cannot be redefined and delivery of this signal always immediately ends the process, which is done by the kernel itself.

Upvotes: 4

dolmen
dolmen

Reputation: 8696

Signal #9 (SIGKILL) can not be trapped. That's how Unix is designed.

But the system does not send that signal when shutting down for maintainance. At least if your daemon behaves correctly. It will normally send the TERM signal (or more exactly what your daemon handling script in /etc/init.d does). Only processes that do not correctly shutdown after a timeout will receive SIGKILL.

So your aim should be to correctly handle the TERM signal and to write the wrapper script in /etc/init.d that will be called when the system is changing runlevel.

Update: You can use the Daemon::Control module for the init script.

Upvotes: 11

Ivan Nevostruev
Ivan Nevostruev

Reputation: 28713

As far as I know you can't capture kill -9. Try kill <pid> instead.

Upvotes: 3

Related Questions