This is the mail archive of the guile@cygnus.com mailing list for the guile project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Semantics of UNIX Signal Handling in Guile


Hello all, 

Background: 
I'm currently thinking about POSIX Threads support in Guile, and
encounter the issues around UNIX signal handling.

In this message, I'm talking about asynchronous signals such as
SIGINT, SIGALRM, SIGQUIT, SIGUSR1, SIGUSR2, and SIGHUP (not about
SIGSEGV, SIGPIPE, and SIGFPE).

In the current implementation of Guile (as of guile-core-19980608 I'm
reading), signal can interrupts C code, and invokes signal handler.
The handler can do anything it wants, as we can bind Scheme function
to the handler.  Even the handler can call 'throw' and change the flow
of control of interrupted C code.

However, this feature of "can interrupt C code", complicates the
requirements to user written C code, because the code have to be
written interrupt-aware style.  Specifically, we have to use
DEFER_INTS/ALLOW_INTS to protect critical section.

The existence of DEFER_INTS/ALLOW_INTS helps very much for supporting
threads as it shows some critical sections (also for threads) clearly.
But IMNSHO, this feature is questionable.

I checked sources of Bash 2.01.1, Python 1.4 Perl 5.004_03, and GNU
Emacs 20.2 to see what's going in those packages.

Here is the table.
===========================================================================
Language Interrupt Handler   Is it safe      Method to protect signal
         Level     call      to use signal?
---------------------------------------------------------------------------
Bash     Interp    Anything   Safe

Python   Interp    Anything   Safe

Perl     C         Anything   Not safe

Guile    C         Anything   Should be safe  DEFER_INTS/ALLOW_INTS

Emacs    C         Anything   Not safe for    
                              USR1/USR2       
					      BLOCK_INPUT/UNBLOCK_INPUT
					      for keyboard interrupt

(1) Don't call signal-non-safe function
 C        C        Limited    Safe

(2) Protect critical section
 C        C        Something  Safe            sigprocmask
                                                 SIG_BLOCK/SIG_UNBLOCK
===========================================================================

(1) and (2) are typical approach of programming in C.  In usual C
programming, we have to be careful to handle asynchronous event,
because interrupts may clobber the consistency.

Bash can "trap" signals to run some function, but it doesn't interrupt
underlying C code normally.  The signal handling routine merely mark
the pending signal flag.  In some parts (e.g. eval) it checks pending
signals and run the handler (calling run_pending_traps).  There is an
exception, when the variable interrupt_immediately is marked, signal
handling routine calls run_pending_traps directly.  With
interrupt_immediately, editing function can be interrupted.

Python can set handler by "signal".  Signal doesn't interrupt
underlying C code, but just mark the pending signal flag.  In some
parts, such as eval and printing function, pending signals checked and
the handler is called.

Perl can set handler and it is called interrupting underlying C code.
I think that it's not safe.  For example, printf is called and
interrupted and handler also calls printf, which clobbers working
buffer of printf.  It seems that there is no code like
DEFER_INTS/ALLOW_INTS of Guile.  Perl is not good for signal driven
programming, I guess.

Emacs can run interrupt driven input mode, and some parts of code is
protected by BLOCK_INPUT/UNBLOCK_INPUT against SIGIO.  This is OK.
Emacs also has signal-USR1-hook and signal-USR2-hook to be executed on
getting SIGUSR1 and SIGUSR2, interruping underlying C code.  This is
not safe, for example, garbage_collect may be interrupted.

			*	*	*

Well, it seems that signal handling is special issue for Perl and
Emacs, and "not-use-heavily" feature.

How about Guile?  It's designed well, but it complicates requirements
of C code, much.  Perhaps it may be easy to write module for Python in
C, as we don't need to care to be interrupted.  Futher, current Guile
code has some parts where DEFER_INTS/ALLOW_INTS mismatch will occur
when assert is failed.

Couldn't we consider the approach of Bash or Python, where signal
handling routine just marks the flag and eval/print routine checks for
pending signal?

Any comments?

Thanks,
-- 
NIIBE Yutaka