in reply to Re: handling HUP signals
in thread handling HUP signals

Almut, thank you for your reply. Here is some test code, I am sorry it is not a 10-liner, but I wanted to maintain the concept of a global object that I have in my application. :)

#!/usr/bin/perl use strict; use Getopt::Std; use Mgr; use Global1; my %OPT; my $ok = getopts("D", \%OPT); my $BASE = "."; daemonize(); start(); sub start { eval { $SIG{HUP} = \&catchHup; $SIG{CHLD} = "IGNORE"; $SIG{INT} = \&catchInt; $SIG{USR1} = \&catchUsr1; if ($MANAGER) { undef $MANAGER; } $MANAGER = new Mgr; $MANAGER->monitor(); }; if ($@) { Global1::error ("Got fatal error:\n$@\n"); catchInt(); } } sub daemonize { require POSIX; open STDOUT, '>/dev/null' or die "Can't write to /dev/null: $!"; open STDERR, '>/dev/null' or die "Can't write to /dev/null: $!"; defined(my $pid = fork) or die "Can't fork: $!"; exit if $pid; POSIX::setsid() or Global1::error ( "Could not setsid\n$!\n" ); `echo $$ > tun_mgr.pid`; } sub catchHup { Global1::error ( "\n\t!!!Got HUP!!!\n" ); $MANAGER->killAll(); Global1::error ( "\n\tRestarting application\n" ); &start(); } sub catchInt { $MANAGER->killAll(); `rm -rf tun_mgr.pid`; Global1::error ( "Parent process $$ exiting\n" ); exit; }

package Mgr; use strict; use Global1; sub new { my $this = {}; $this->{children} = {}; bless $this; return $this; } sub killAll { my $this = shift; $SIG{CHLD} = "IGNORE"; foreach (keys %{$this->{children}}) { my $cpid = $this->{children}->{$_}->{pid}; if (kill INT => $cpid) { Global1::error ("Killed child $cpid\n"); } delete $this->{children}->{$_}; } } my $usr1 = 0; my $usr2 = 0; sub monitor { my $this = shift; my $num = 0; my $pid; my $ppid = $$; while ($num < 2) { unless ($pid = fork()) { # Child $SIG{USR1} = \&doPing; $SIG{INT} = \&gotINT; $SIG{HUP} = 'IGNORE'; $SIG{USR2} = 'IGNORE'; CHILD_START: while (! $usr1) { Global1::error ( "Child $$ sleeping for 10 seconds\n" +); sleep(10); } $usr1 = 0; eval { `echo 1 > $$`; my $numkill = kill 'USR2' => $ppid; Global1::error ( "\t$$ Sent SigUSR2 to parent proc +ess \n" ); goto CHILD_START; }; sub doPing { $usr1 = 1; } sub gotINT { Global1::error ( "$$ got INT signal - exiting\n" ); exit; } } # Parent Code $this->{children}->{$num}->{pid} = $pid; Global1::error ( "Spawned pinger process $pid child ID # $num\ +n" ); $num++; } foreach my $ch (keys %{$this->{children}}) { my $numkill = kill 'USR1' => $this->{children}->{$ch}->{pi +d}; Global1::error ( "Parent $$ sent SigUSR1 to process ".$thi +s->{children}->{$ch}->{pid}." \n" ); } $SIG{USR2} = \&catchUsr2; $SIG{HUP} = \&main::catchHup; $SIG{CHLD} = "IGNORE"; $SIG{INT} = \&main::catchInt; if ($DEBUG) { my $msg = ""; foreach (keys %SIG) { $msg .= "$_ => $SIG{$_}\n"; } Global1::error ( "Parent's SIG hash:\n$msg\n" ); } HANGOUT: while (! $usr2) { sleep 1; } $usr2 = 0; my $done = 0; $num = 0; foreach $num (keys %{$this->{children}}) { my $fc = $this->{children}->{$num}->{pid}; if (-e $fc) { Global1::error ( "Parent process $$ recieved USR2 sign +al from child $fc\n" ); unlink $fc; kill "USR1" => $fc; last; } } goto HANGOUT; sub catchUsr2 { $usr2 = 1; } } 1;

package Global1; require Exporter; @ISA = qw(Exporter); @EXPORT = qw ( $MANAGER $DEBUG ); $MANAGER = ""; $DEBUG = 1; sub error { my $mes = shift; my $date = scalar (localtime (time)); open (LOG, ">>logfile") or die "Could not open logfile for write:\ +n$!\n"; print LOG "$date\t $mes\n"; close LOG; } 1;

Replies are listed 'Best First'.
Re^3: handling HUP signals
by almut (Canon) on May 22, 2008 at 23:37 UTC

    I haven't investigated this in every detail, but it looks to me like you're never exiting your catchHup() signal handler, once it got called. At the end of the handler you call start() which then calls $MANAGER->monitor();. At the end of that routine you have

    HANGOUT: while (! $usr2) { sleep 1; } ... goto HANGOUT;

    which looks like an endless loop to me...  i.e. you never leave that function, and thus you never leave the signal handler you called it from. And, as you probably know, signal handlers will not be reactivated before you have left them...

    Update: Generally, it's a good idea to not do too much within a signal handler routine. In most cases it's best to just set some flag to which you can react in the main program's loop.

      Almut, you are absolutely correct. The problem was not exiting the signal handler. The solution was simply to have a global variable that is set in the catchHup handler and take the appropriate steps once that variable is set. Thanks!!!