in reply to Setting signal handlers considered unsafe?

Have you tried any of the signal stuff in POSIX? I'm thinking of sigprocmask in particular.

I'm no signal wizard, but try suspending the ALRM signal while you set the handler. When you reenable the ALRM handler, any pending ALRMs should be triggered.

Let us know what you come up with, I'm curious.


TGI says moo

Replies are listed 'Best First'.
Re^2: Setting signal handlers considered unsafe?
by gnosek (Sexton) on Nov 05, 2008 at 20:49 UTC

    Just tried on my home Ubuntu system (perl 5.8.8). Ran for a few seconds (a new record!) and crashed with

    Unable to create sub named "" at crash.pl line 15.

    This is the exact code I used:
    #!/usr/bin/perl use warnings FATAL => qw( all ); use strict; use POSIX qw( :signal_h ); $SIG{ALRM} = sub { print "SIGARLM: main handler\n" }; sub f { my $sigset = POSIX::SigSet->new; my $blockset = POSIX::SigSet->new( SIGALRM ); sigprocmask(SIG_BLOCK, $blockset, $sigset ); local $SIG{ALRM} = sub { print "SIGALRM\n" }; # line 15 sigprocmask(SIG_SETMASK, $sigset ); } if (fork) { # parent f while 1; } else { # child sleep 1; print "child starting\n"; 1 while kill ALRM => getppid; }

      I'm no master of perlguts either, but it occurs to me that there are two places where you are vulnerable to signal changes: 1. when you set the localized handler, 2. when the localization goes out of scope and the old handler is installed.

      Your code traps only one of the two vulnerable points.

      What happens if you do:

      #!/usr/bin/perl use warnings FATAL => qw( all ); use strict; use POSIX qw( :signal_h ); $SIG{ALRM} = sub { print "SIGARLM: main handler\n" }; sub f { my $sigset = POSIX::SigSet->new; my $blockset = POSIX::SigSet->new( SIGALRM ); my $old_handler = $SIG{ALRM}; # Install new handler sigprocmask(SIG_BLOCK, $blockset, $sigset ); $SIG{ALRM} = sub { print "SIGALRM\n" }; # line 15 sigprocmask(SIG_SETMASK, $sigset ); # spin a bit. my $x; $x = $_ for 1..10; # Restore old handler. sigprocmask(SIG_BLOCK, $blockset, $sigset ); $SIG{ALRM} = $old_handler; sigprocmask(SIG_SETMASK, $sigset ); } if (fork) { # parent f while 1; } else { # child sleep 1; print "child starting\n"; 1 while kill ALRM => getppid; }


      TGI says moo

      On my system (This is perl, v5.8.8 built for i386-linux-thread-multi) your script ran for many minutes, until I stopped it. I am running CentOS 5.2 with the CentOS distribution of perl.

      Is it possible that your system is not running with safe/deferred signals (environment variable PERL_SIGNALS set to "unsafe")?

        Is it possible that your system is not running with safe/deferred signals (environment variable PERL_SIGNALS set to "unsafe")?

        No. Rather not. All my perl binaries are distribution-provided (perl -V | grep -i sig only returns hint=recommended, useposix=true, d_sigaction=define) and I don't have anything containing 'PERL' in my environment either. The plot thickens... ;)