develooper Front page | perl.perl5.porters | Postings from January 2001

Re: Does perl really need to use sigsetjmp? (18% performance hit)

Thread Previous
From:
Alan Burlison
Date:
January 9, 2001 06:15
Subject:
Re: Does perl really need to use sigsetjmp? (18% performance hit)
Message ID:
3A5B1CD8.A69CCE36@uk.sun.com
Raphael Manfredi wrote:

> The problem is to know the semantics we wish to guarantee when one
> does this:
> 
>         $SIG{ALRM} = 'IGNORE';
> 
>         eval { &foo };
>         print "back from foo()\n";
>         alarm(2);
>         select(undef, undef, undef, 4);
> 
>         sub TIMEOUT {
>                 die "TIMEOUT";
>         }
> 
>         sub foo {
>                 $SIG{ALRM} = 'TIMEOUT';
>                 alarm(2);
>                 select(undef, undef, undef, 4);
>         }
> 
> For me (Linux 2.4.0, perl 5.005_03), it yields:
> 
>         back from foo()
>         TIMEOUT at /home/ram/tmp/alarm line 9
> 
> Is this what is expected?
> 
> I wonder where sigsetjmp() comes into play here, because what is
> happening shows that the signal mask is not restored, and that ALRM
> continues to be trapped even though we came back through a siglongjmp()?

Goodness knows what is happening here - tracing the program shows
Perl_sighandler being called when the first alarm call expires, but it
doesn't then seem to call the script-level signal handler.  I suspect
that because the alarm is caught inside an eval, perl is mistakenly
siglongjmp-ing out of the eval *before* calling the interrupt handler. 
The subsequent alarm/select pair then works as expected because it
hasn't been called inside an eval block, and the siglongjmp doesn't
therefore happen.  Here is the evidence:

(/tmp/a:14)     alarm
    =>  IV(0)
(/tmp/a:14)     nextstate
    =>
(/tmp/a:15)     undef
    =>  SV_UNDEF
(/tmp/a:15)     undef
    =>  SV_UNDEF  SV_UNDEF
(/tmp/a:15)     undef
    =>  SV_UNDEF  SV_UNDEF  SV_UNDEF
(/tmp/a:15)     const(IV(4))
    =>  SV_UNDEF  SV_UNDEF  SV_UNDEF  IV(4)
(/tmp/a:15)     sselect
(/tmp/a:15)     ENTER scope 6 at perl.c:1608
(/tmp/a:15)     ENTER scope 7 at pp_hot.c:2303
Entering block 0, type SUB
    =>  PV("ALRM"\0)
(/tmp/a:15)     nextstate
    =>
(/tmp/a:9)      pushmark
    =>  *
(/tmp/a:9)      const(PV("TIMEOUT"\0))
    =>  *  PV("TIMEOUT"\0)
(/tmp/a:9)      die
Unwinding block 0, type SUB
(/tmp/a:9)      (Found eval #1)
Unwinding block 2, type SUB
Leaving block 1, type EVAL
(/tmp/a:3)      LEAVE scope 3 at pp_ctl.c:1385
    =>
(/tmp/a:3)      nextstate
    =>
(/tmp/a:4)      pushmark
    =>  *
(/tmp/a:4)      const(PV("back from foo()\n"\0))
    =>  *  PV("back from foo()\n"\0)
(/tmp/a:4)      print
    =>  SV_YES

There is so much brokenness and platform-dependent behaviour in the area
of perl signal handling that I don't think a switch from sigsetjmp to
setjmp is going to make any discernable difference.

Alan Burlison

Thread Previous


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About