jjharr
asked on
signal trapping in a daemonized server
I have a Perl daemon that operates as both a networking client and a server using various modules. It works fine.
Except... I need to introduce use of a periodic SIGALRM handler and that doesn't work fine. The handler runs once and then the program dies silently. Alarm code is below. I've grepped through most of the module sources and as far as I'm aware, none of them are using SIGALRM. If I eliminate the networking and just run a daemon with a while(1) loop, it works fine (but that's not so useful). I don't even know how to debug it. Any help would be very welcome.
Except... I need to introduce use of a periodic SIGALRM handler and that doesn't work fine. The handler runs once and then the program dies silently. Alarm code is below. I've grepped through most of the module sources and as far as I'm aware, none of them are using SIGALRM. If I eliminate the networking and just run a daemon with a while(1) loop, it works fine (but that's not so useful). I don't even know how to debug it. Any help would be very welcome.
local $SIG{'ALRM'} = \&logme;
setitimer(ITIMER_REAL, 10, 10);
sub { $log->info("Alarm handler");}
ASKER
Here's a super simple test case to illustrate the problem. As shown it breaks on the first run of the handler. Comment setitimer() out, and the problem goes away.
#!/usr/bin/perl
use IO::Socket;
use Time::HiRes qw(setitimer ITIMER_REAL time);
defined(my $pid=fork) or die "Can't fork: $!";
exit if $pid;
setsid or die "Can't start a new session: $!";
$SIG{'ALRM'} = \&logme;
setitimer(ITIMER_REAL, 10, 10);
my $sock = new IO::Socket::INET (
"Proto" => "tcp",
"LocalPort" => 8819,
"Reuse" => 1,
"Listen" => 1
) or die "Server croaked";
while($client = $sock->accept())
{
}
sub logme {
print "hello\n";
}
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
The problem is how the timeout in accept is handled. See this example:
#!/usr/bin/perl
use Time::HiRes qw(setitimer ITIMER_REAL time);
$SIG{'ALRM'} = \&logme;
setitimer(ITIMER_REAL, 3, 3);
print "Waiting...\n";
1 while(1);
print "Done waiting\n";
sub logme {
print "hello\n";
}
open(STDERR, ">/var/log/your_program.er
The interval timers are not supported by windows. You didn't say which OS you were using, but I'm guessing some form of linux from your Tag.