jimmy5804 has asked for the wisdom of the Perl Monks concerning the following question:

I have a daemonized server (Linux/Perl 5.8.8) and I would like to perform a task every few minutes. Using a SIGALRM handler seems to not work because it causes accept() to return. So I'm trying to fork off a daemon process that just sleeps and sends SIGUSR1 to my process. However, my server dies the first time the signal handler is run. Here's a simple reduced case with the same behavior:

The server:
#!/usr/bin/perl use IO::Socket; #defined(my $pid=fork) or die "Can't fork: $!"; #exit if $pid; #setsid or die "Can't start a new session: $!"; my $sock = new IO::Socket::INET ( "Proto" => "tcp", "LocalPort" => 8819, "Reuse" => 1, "Listen" => 1 ) or die "Server croaked"; $SIG{'USR1'} = \&sigHandler; system("./sleep.pl $$"); while($client = $sock->accept()) { } sub sigHandler { print "SIGNAL HANDLER\n"; }
The forked process (sleep.pl):
#!/usr/bin/perl $ppid = $ARGV[0]; print "$ppid"; defined(my $pid=fork) or die "Can't fork: $!"; exit if $pid; setsid or die "Can't start a new session: $!"; while(1) { sleep(10); print "DISPATCHING SIGNAL\n"; kill(SIGUSR1, $ppid); }
If you know why my server is dying or you know A Much Better way to accomplish the same objective, I'd be very appreciative.

Replies are listed 'Best First'.
Re: Catching a signal causes my socket server to die
by ikegami (Patriarch) on Jan 07, 2009 at 09:12 UTC

    Using a SIGALRM handler seems to not work because it causes accept() to return.

    Doesn't the same thing happen with SIGUSR1? If so, just loop back if the error was EINTR.

    use Errno qw( EINTR ); do { while (my $client = $sock->accept()) { ... } } while ($! == EINTR);
      My understanding is that accept() returns on SIGALRM because it uses sleep() internally which uses SIGALRM in it's implementation - so you basically have two SIGALRM handlers. I had hoped that I could avoid this with SIGUSR1, but.... apparently not.
        accept is a system call. It doesn't use sleep, a different system call. Mind you, both put the process in a sleep state, and both are reactive to signals. Any signals, not just ALRM.
      By the way, I found the accept() loop in the 3rd party server module I was using and modified it. It works, it's a generally applicable piece of knowledge for me, and it seems like the right solution for my problem. Thanks much!
Re: Catching a signal causes my socket server to die
by lakshmananindia (Chaplain) on Jan 07, 2009 at 09:15 UTC
    Using a SIGALRM handler seems to not work because it causes accept() to return.
    while() { my $ret=accept($client,$server); next if (not defined($ret)); . . }
    Instead of using accept inside the parenthesis, use it inside the loop and continue if succeeded. It worked for me.
      That will result in real errors causing the application to enter a tight, infinite loop.
Re: Catching a signal causes my socket server to die
by weismat (Friar) on Jan 07, 2009 at 11:48 UTC
    Why are you using signals for communication inside your daemon?
    Make yourself familiar with threads and then share the needed data. Processing gets then very clean.
      I guess I could have one thread sleep. I do really need to learn threads but in this particular case, Real Life wants answers from me right away from me I'm afraid.