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

I've been doing this for a while but I'm just starting on daemon code and I thought signal handlers sounded like a good idea (it lets me close sockets and database handles, etc.) So I tried it, and got stuck right here... I've read everything I can find on signal handlers, and this looks right to me:
sub GotSignal($) { my $sig = shift; print "Got a $sig signal, exiting\n"; exit(0); } # Install signal handlers local $SIG{HUP} = 'IGNORE'; local $SIG{QUIT} = \&GotSignal('quit'); while (1) { # do stuff }
..But it doesn't work. As soon as the code hits the line where I assign a handler to $SIG{QUIT}, it runs that subroutine and exits. But if I do this:
# Install signal handlers local $SIG{HUP} = 'IGNORE'; local $SIG{QUIT} = sub { my $sig = shift; print "Got a $sig sign +al, exiting\n"; exit(0); }; while (1) { # do stuff }
The second example works as expected. This is on Linux (RH 6.2) runing perl5 (5.0 patchlevel 5 subversion 3). Anyone have any ideas? All help appreciated.
"Non sequitur. Your facts are un-coordinated." - Nomad

Replies are listed 'Best First'.
(tye)Re: Strange SIGNAL HANDLER behavior...
by tye (Sage) on Oct 24, 2001 at 23:32 UTC

    Note that Perl already passes in the name of the signal to the signal handler so simply: $SIG{QUIT}= \&GotSignal; would produce the message Got a QUIT signal, exiting so if the case of the name bothers you, another alternative would be:

    sub GotSignal { my $sig= ucfirst lc shift; print "Got a $sig signal, exiting\n"; exit(0); }

            - tye (but my friends call me "Tye")
Re: Strange SIGNAL HANDLER behavior...
by dws (Chancellor) on Oct 24, 2001 at 23:07 UTC
    The problem you're running into is that you're actually invoking your signal handler when you're setting it up. The line   local $SIG{QUIT} = \&GotSignal('quit'); is creating a reference to the result of invoking GotSignal, and assign the reference to $SIG{QUIT}. Not what you intended, but Perl is just following orders.

    One alternative to your second, working code fragment is   local $SIG{QUIT} = sub { GotSignal('quit') };

      That makes perfect sense, and is kinda what I was thinking.. But: 1) why do the Camel, Llama, and Goat all show examples like this, then? Perl Cookbook, pg 587:
      $SIG{INT} = \&got_int;
      ..and 2) Why doesn't the hard anonymous subroutine reference also execute the subroutine immediately? Doesn't this say set $SIG{QUIT} to the value returned by sub{ GotSignal('quit'} }; ??
      local $SIG{QUIT} = sub { GotSignal('quit') };
      I'm just trying to make sense of Perl's internal logic here.. Maybe that's my first mistake... ;-)
      "Non sequitur. Your facts are un-coordinated." - Nomad

        The difference is that you have parens following the sub name, which parses as a subroutine call. You can't create a reference to a sub invocation with particular arguments, you can only create a reference to a sub. If you need to set values in the sub, you'll need closures.