Emphasis added:

From: John Cowan <xxxxxx@ccil.org>
Date: Saturday, August 17, 2019 12:35 PM

 I suggest that SRFI 170 get back the ability to ignore signals, which is much more straightforward than trapping them.  Here's a proposal:

(with-signals-ignored signal-list thunk)

Signal-list is a list of signal numbers. Signals that are already ignored, cannot be ignored, or are being trapped by the implementation are filtered out of the list.  The thunk is then executed under the control of dynamic-wind, using a before-thunk that ignores each of the remaining signals and an after-thunk that restores the default disposition.


Right now a SRFI-170 implementor doesn't have to get very deep into an implementation, the most is in the I/O section where you have to convert from a port to a file descriptor, and create 4 kinds of ports given a file descriptor.  I found that wasn't very difficult to do in a "monkey sees, monkey does" fashion.

This addition would require an implementor to dig some more IF the Scheme implementation does any default signaling handling.  Which is not the case for Chibi Scheme, except for an optional print backtrace on getting a segfault compile option I just noticed, plus the fancy REPL library, and the process library that also does fork etc.

A quick recursive grep of Chicken Scheme indicates a fair amount of work might be required, see for example the top level runtime.c "Runtime code for compiler generated executables" file:

#include <signal.h>
  pass_serious_signals = 1,
  serious_signal_occurred = 0,
static C_TLS int signal_mapping_table[ NSIG ];
static void global_signal_handler(int signum);
  pass_serious_signals = 0;
    sigfillset(&sa.sa_mask); /* See note in C_establish_signal_handler() */
    sa.sa_handler = global_signal_handler;
  /* setup signal handlers */
  if(!pass_serious_signals) {
    C_signal(SIGBUS, global_signal_handler);
    C_signal(SIGILL, global_signal_handler);
    C_signal(SIGFPE, global_signal_handler);
    C_signal(SIGSEGV, global_signal_handler);
  memset(signal_mapping_table, 0, sizeof(int) * NSIG);
    C_signal(C_PROFILE_SIGNAL, global_signal_handler);
/* This is called from POSIX signals: */
void global_signal_handler(int signum)
    if(serious_signal_occurred || !chicken_is_running) {
    else serious_signal_occurred = 1;
    /* unblock signal to avoid nested invocation of the handler */
    default: panic(C_text("invalid serious signal"));
  else C_raise_interrupt(signal_mapping_table[ signum ]);
  C_signal(signum, global_signal_handler);
  pass_serious_signals = 1;
  serious_signal_occurred = 0;
  serious_signal_occurred = 0;
   * is used in the signal handler, because it may not malloc.
       * Drop signals if too many, but don't queue up multiple entries
       * for the same signal.
C_regparm C_word C_fcall C_establish_signal_handler(C_word signum, C_word reason)
  if(reason == C_SCHEME_FALSE) C_signal(sig, SIG_IGN);
    signal_mapping_table[ sig ] = C_unfix(reason);
    /* The global signal handler is used for all signals, and
       manipulates a single queue.  Don't allow other signals to
    newsig.sa_handler = global_signal_handler;
    C_signal(sig, global_signal_handler);

A minimal effort in groking the above suggests it'll be seriously less fun than creating the Chibi Scheme I/O procedures.

See also for example these NEWS items, the ones grouped together were from the same release:

In Runtime system:

  - Delivery of signals in other OS-level threads is now dealt with
    in a more robust way (#1232) (thanks to Joerg Wittenberger).

  - The signal handling code can no longer trigger "stack overflow" or
    "recursion too deep or circular data encountered" errors (#1283).

  - On systems that provide sigprocmask(2), segmentation violations, illegal
    instruction signals, bus errors and floating-point exceptions are now caught
    and trigger normal error-processing (including a backtrace). The handling
    of these so called "serious" signals can be disabled by passing the
    "-:S" runtime option to executables.

  - signals are queued to some extent and the interrupt handling has
    been cleaned up somewhat
  - the interpreter handles SIGINT directly - loading the "posix" unit
    is not needed anymore to handle this feature
  - signal masks were accidentally reset upon GC for some platforms; use
    sigsetjmp/siglongjmp on BSD, Linux, MacOS X and Haiku

In Core libraries:

  - thread-join! now works correctly even if the waiting thread was
     prematurely woken up by a signal.

  - The "signal/bus" signal identifier was missing.
  - Added setter-procedure for "signal-mask".

Chez Scheme also looks non-trivial, and I don't have any idea how signals work with native POSIX threads, all my multi-threaded in anger work was done on Windows (NT).

- Harold