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

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

Thread Previous | Thread Next
From:
Alan Burlison
Date:
January 9, 2001 03:17
Subject:
Re: Does perl really need to use sigsetjmp? (18% performance hit)
Message ID:
3A5AF359.E5C81645@uk.sun.com
Nick Ing-Simmons wrote:

> Apparently not. I cannot at present think what sigsetjmp() gains
> us. Do you have an guidelines which say "use sigsetjmp() if your code does X?"

You need to use it if you want the signal mask restored when you do the
siglongjmp.  The typical use would be if you are going to do a
siglongjmp out of a signal handler.  POSIX doesn't specify what happens
to the signal mask if you use setjmp/longjmp in a signal handler - it
could either be restored or left with the pending signal blocked. 
sigsetjmp/siglongmp have specified semantics - if the second parameter
to sigsetjmp is non-zero, a subsequent siglongjmp will restore the
signal mask.

In perl terms, I think the only time this would happen is if you did a
die inside a signal handler, and expected to go back to an enclosing
eval() with the signal handler restored.  You could also use it for
timing out long operations, using SIGALRM and an alarm() call, but note
the caveat in paragraph 3 below.

Here are the appropriate bits of the sigsetjmp manpage:

     The sigsetjmp() function saves the calling process's  regis-
     ters  and stack environment (see sigaltstack(2)) in  env for
     later use by siglongjmp(). If   savemask  is  non-zero,  the
     calling  process's  signal  mask  (see  sigprocmask(2))  and
     scheduling parameters (see priocntl(2)) are also saved.

     The siglongjmp() function restores the environment saved  by
     the  last  call  of  sigsetjmp()  with the corresponding env
     argument. After siglongjmp()  completes,  program  execution
     continues  as  if  the corresponding call to sigsetjmp() had
     just returned the value val. The siglongjmp() function  can-
     not   cause   sigsetjmp()   to   return  the  value  0.   If
     siglongjmp() is invoked with a second argument  of  0,  sig-
     setjmp()  will  return  1.  At the time of the second return
     from sigsetjmp(), all external  and  static  variables  have
     values as of the time siglongjmp() was called.

     If a signal-catching function interrupts sleep(3C) and calls
     siglongjmp()  to  restore  an environment saved prior to the
     sleep() call, the action associated with SIGALRM and time it
     is  scheduled  to  be  generated are unspecified. It is also
     unspecified whether the SIGALRM signal  is  blocked,  unless
     the  process's  signal  mask  is  restored  as  part  of the
     environment.

     The  siglongjmp() function restores the saved signal mask if
     and  only  if the  env argument was initialized by a call to
     the sigsetjmp() function with a non-zero  savemask argument.

Having the defined semantics provided by sigsetjmp/siglongjmp is nice,
but because sigsetjmp is called so frequently, and because it requires a
system call each time, the overhead is intolerable in performance terms
- see Ilya's recent '[PATCH 5.7.0] speeding up object
creation/destruction 4x times' thread
(http://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/2000-12/msg00798.html),
part of which was to revert back to using setjmp/longjmp instead of
sigsetjmp/siglongjmp.

As I recollect, the relevant bit of the perl documentation recommends
that you explicitly re-establish signal disposition inside the handler -
if this is done correctly, sigsetjmp doesn't actually achieve anything
other than a significant slowdown of the entire interpreter.

What I don't understand is why we must do a sigsetjmp for *every* block
in the interpreter - I'm surmising here, but surely sigsetjmp is only
required if a) the block is wrapped in an eval and b) there is an active
signal handler when the block is entered?  The current approach seems to
be a bit of a blunderbuss, and I for one think the performance penalty
of using sigsetjmp is just to heavy to bear.

Don't forget that due to a long-standing breakage in
sigsetjmp/siglongjmp on Solaris x86, sigsetjmp was disabled on that
platform, and I can't recollect anyone reporting any bugs as a result.

My vote is for us to revert back to setjmp, and as I indicated I may
well just disable it regardless when I integrate 5.6.1 into Solaris.

Alan Burlison

Thread Previous | Thread Next


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