This is the mail archive of the email@example.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]|
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