#!/usr/bin/perl # test_signals # This script is intended to illustrate the effect of various signals # Cameron Hayne (macdev@hayne.net) June 2003 use strict; use warnings; my $delay = 1; my $count = 0; # function that gets called upon quit sub finish() { print "Cleaning up, please wait ...\n"; for (1 .. 5) { print ".\n"; sleep 1; } print "Finished cleaning up, now exiting\n\n"; exit; } # Signal Handlers: # These functions get invoked when the script receives the corresponding signal # Note: signal numbers are in /usr/include/sys/signal.h sub handle_SIGHUP() # number 1 { print "\nReceived HUP signal\n"; print "Resetting state\n\n"; $delay = 1; $count = 0; } sub handle_SIGINT() # number 2 { print "\nReceived INT signal\n"; print "Do it again to get the default action\n\n"; $SIG{INT} = 'DEFAULT'; } sub handle_SIGQUIT() # number 3 { print "\nReceived QUIT signal\n"; print "But I'm not going to do anything about it!\n\n"; } sub handle_SIGABRT() # number 6 { print "\nReceived ABRT signal\n"; print "But I'm not going to do anything about it!\n\n"; } sub handle_SIGKILL() # number 9, number 9, number 9, ... { # this will never happen - KILL cannot be caught ! print "\nReceived KILL signal\n"; } sub handle_SIGTERM() # number 15 { print "\nReceived TERM signal\n"; print "Do it again to get the default action\n\n"; $SIG{TERM} = 'DEFAULT'; } sub handle_SIGSTOP() # number 17 { # this will never happen - STOP cannot be caught ! print "\nReceived STOP signal\n"; } sub handle_SIGUSR1() # number 30 { print "\nReceived USR1 signal\n"; print "Changing delay\n\n"; $delay = 1 if ++$delay > 3;; } sub setup_signals() { $SIG{HUP} = \&handle_SIGHUP; # 1 $SIG{INT} = \&handle_SIGINT; # 2 $SIG{QUIT} = \&handle_SIGQUIT; # 3 $SIG{ABRT} = \&handle_SIGABRT; # 6 $SIG{KILL} = \&handle_SIGKILL; # 9 $SIG{TERM} = \&handle_SIGTERM; # 15 $SIG{STOP} = \&handle_SIGSTOP; # 17 $SIG{USR1} = \&handle_SIGUSR1; # 30 } sub setup_input() { use Fcntl; # We want non-blocking input (so the script doesn't wait for input) # Note that it might be necessary to call this again if STDIN got reset # by the shell (e.g. after a STOP signal) my $flags = 0; fcntl(STDIN, F_GETFL, \$flags) or die "Couldn't get flags for STDIN : $!\n"; $flags |= O_NONBLOCK; fcntl(STDIN, F_SETFL, $flags) or die "Couldn't set flags for STDIN: $!\n"; } sub check_for_quit() { my $input; if (read(STDIN, $input, 1)) { return 1 if lc($input) eq 'q'; } return 0; } # -- MAIN -- setup_signals(); setup_input(); print "\nWelcome to the 'testsignals' script\n"; print "The PID of this script is $$\n"; print "Try sending it various signals via the 'kill' command\n"; print "from another window. (E.g. kill -1 $$)\n"; print "Signals: HUP = 1, INT = 2, QUIT = 3, KILL = 9\n"; print " TERM = 15, STOP = 17, USR1 = 30\n"; print "Also try keyboard actions like control-C, control-Z, control-\\\n"; print "\n"; while (1) { ++$count; print "Working $count (Type q followed by Return to quit)\n"; if (check_for_quit()) { print "Okay, I'm quitting now\n"; finish(); } sleep $delay; } print "How did we get here? (Shouldn't ever happen)\n"; exit;