sigaction: queried SA_RESTART value varies by FreeBSD version?

Matthew Dillon dillon at apollo.backplane.com
Mon May 7 21:27:17 UTC 2007


:While writing a regression test for signal-handling as related to socket 
:locking, I ran into the following slightly surprising issue.  In order to test 
:properly, I need the recv(2) system call to not automatically restart.  Being 
:a bit on the cautious side, I decided I would check the SA_RESTART disposition 
:of the signal before setting it, and was a bit surprised to see that the 
:debugging output varied across FreeBSD versions.  In particular, I was using 
:SIGHUP in my tests, which seems to have recently changed (if kernel versions 
:are at all meaningful -- perhaps the field is just garbage).
:
:I will be the first to admit I don't know how this is supposed to work, but 
:variation in the default value of SA_RESTART for signals strikes me as a 
:worrying thing.  Could someone point me in the right direction here?
:
:Robert N M Watson
:Computer Laboratory
:University of Cambridge

    When a signal interrupts a tsleep, SA_RESTART tells tsleep whether to
    return ERESTART or EINTR.  The ERESTART can be fed *almost* all the
    way back to userland.  The kernel silently catches ERESTART and adjusts
    the return pc in the trap frame back to the beginning of the
    int 0x80 instruction.  Returning to userland then allows any pending
    signal handlers to run and when the signal handler returns the original
    userland trap frame will restarts the system call.

    I think a lot of this might be due to exec's.  Only signal handlers
    are not inherited by an exec.  Most signal flags ARE inherited by exec.
    The flags you see may have been adjusted by the parent process (e.g. like
    the shell or ssh or cron or getty or whatever) before your program was
    run.   Usually: caught signals are reset, signal handlers are reset,
    NOCLDWAIT is cleared on SIGCHLD, and the alternate-stack flag is 
    cleared on all signals.  On exec.  Something like that.

    Normally any signal that would cause an infinite loop on restart,
    such as SIGSEGV, defaults to not restarting.  Nominal handleable signals
    such as SIGHUP usually leave SA_RESTART set.

    SIGPIPE is a special case in that it may or may not be a synchronous
    signal.  Kinda weird.  A shell pipe might change the flag for piped
    commands (I dunno, you'd have to check).

    SIGSTOP and SIGCONT are special cases.  These signals are usually handled
    by the kernel internally and the SA_RESTART flag is probably irrelevant.

    So what you are reporting may be as much artifacts of the exec chain
    leading up to and including the shell you ran the program from then
    anything else.

						-Matt



More information about the freebsd-current mailing list