Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things

Can't catch signals after an exec?

by mattk (Pilgrim)
on Mar 19, 2005 at 10:09 UTC ( #440900=perlquestion: print w/ replies, xml ) Need Help??
mattk has asked for the wisdom of the Perl Monks concerning the following question:

Given this piece of code:
$sub = sub { exec "perl $0" }; $SIG{INT} = $sub; $SIG{USR1} = $sub; print ++$counter while 1;
Each signal handler works, but only once. After that type of signal has been delivered, that signal ceases to have an effect. Why is this so? Edit: My test code was basically the same as sh1tn's, and I get this output, from perl v5.8.1-RC3, running under OS X 10.3.8:
[matt@powerbook test] perl 1 2 3 4 ^C1 2 3 4 ^C5 ^C^C6 ^C^C7 ^C8 ^Z [1]+ Stopped perl

Comment on Can't catch signals after an exec?
Select or Download Code
Replies are listed 'Best First'.
Re: Can't catch signals after an exec?
by derby (Abbot) on Mar 19, 2005 at 13:56 UTC
    from perlipc:

    Not all platforms automatically reinstall their (native) signal handlers after a signal delivery. This means that the handler works only the first time the signal is sent. The solution to this problem is to use "POSIX" signal handlers if available, their behaviour is well-defined.

    So to rework your example with the one from perlipc:

    !/usr/bin/perl -w use POSIX (); use FindBin (); use File::Basename (); use File::Spec::Functions; $|=1; # make the daemon cross-platform, so exec always calls the script # itself with the right path, no matter how the script was invoked. my $script = File::Basename::basename($0); my $SELF = catfile $FindBin::Bin, $script; # POSIX unmasks the sigprocmask properly my $sigset = POSIX::SigSet->new(); my $action = POSIX::SigAction->new('sigHUP_handler', $sigset, &POSIX::SA_NODEFER); POSIX::sigaction(&POSIX::SIGINT, $action); sub sigHUP_handler { print "got SIGINT\n"; exec($SELF) or die "Couldn't restart: $!\n"; } code(); sub code { my $c = 0; while (++$c) { sleep 2; print "$$ - $c\n"; } }


    Update: Sorry forgot to tell you. I have the same platform as you (Mac OS X 10.3.8, perl v5.8.1-RC3)

    Update: And a lot more like your original code:

    #!/usr/bin/perl use POSIX(); $|=1; $sub = sub { exec "$0" }; # POSIX unmasks the sigprocmask properly my $sigset = POSIX::SigSet->new(); my $action = POSIX::SigAction->new( $sub, $sigset, &POSIX::SA_NODEFER ); POSIX::sigaction(&POSIX::SIGINT, $action); print (++$counter), sleep 1 while 1
      In your reworking of the perlipc example, you use HUP and INT interchangeably. Did you intend to use one xor the other?

        Nope ... just a typo. It should one or the other. In the perldocs, they describe HUP but the OP was only interested in INT -- I foobar-ed the example by switching (but in this case it only matters from a maintenance/consistency view -- the signal SIGINT should probably not be handled my a method named sigHUP!).

Re: Can't catch signals after an exec?
by sh1tn (Priest) on Mar 19, 2005 at 10:47 UTC
    The signals are catched each time, not only once.
    With exec() this program replaces itself with itself($0) thus starting a fresh copy:
    $sub = sub { exec "perl $0" }; $SIG{INT} = $sub; $SIG{USR1} = $sub; $|++; print (++$counter), sleep 1 while 1 # E:\kod> ###>Ctrl+C # 1234567 # E:\kod>123 ###>Ctrl+C # E:\kod>123 ###>Ctrl+C # E:\kod>123 ###>Ctrl+C # E:\kod>1234567
    obviously useless code ... my mistake to take ones time ...

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://440900]
Approved by bart
Front-paged by ww
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others imbibing at the Monastery: (4)
As of 2015-11-27 05:11 GMT
Find Nodes?
    Voting Booth?

    What would be the most significant thing to happen if a rope (or wire) tied the Earth and the Moon together?

    Results (718 votes), past polls