> From: Mikael Djurfeldt <[EMAIL PROTECTED]>
> Date: 29 Apr 2000 01:03:24 +0200
> 
> Marius Vollmer <[EMAIL PROTECTED]> writes:
> 
> > Guile is in a loop, calling take_signal, marking the signal_async, and
> > then returning from the signal handler only to get the sig11 again,
> > without making any progress.
> > 
> > I don't know enough about Unix signals, and much less about how Guile
> > handles Unix signals, to know what to do about this.  I don't think
> > that Guile has always behaved in this way, but I can't say for sure.
> > 
> > I think that Guile should not return from its signal handler for
> > non-continueable signals, like SIGSEGV, SIGILL and SIGBUS.  It should
> > directly throw to wherever is appropriate.
> 
> Marked asyncs are not handled until SCM_ASYNC_TICK is performed.
> Previously, it was performed at each *ALLOW_INTS.
> 
> As a preparation for POSIX threading, I made this change:
> 
> 2000-03-13  Mikael Djurfeldt  <[EMAIL PROTECTED]>
> 
>       * __scm.h (SCM_ALLOW_INTS, SCM_REALLOW_INTS): Removed call to
>       SCM_ASYNC_TICK.  (This is a preparation for POSIX threads support,
>       and kind of an experiment: Will this cause problems?)
> 
> Probably, the change in behaviour we see is that, earlier, the signal
> was actually handled by an SCM_ASYNC_TICK before take_signal is called
> again.  (Since I'm now visiting MIT, I have no time looking into the
> details of this, however.)
> 
> The solution you suggest (non-continuable signals) seems good.

Previously the signal handler wouldn't have returned: take_signal
calls scm_system_async_mark which calls SCM_REALLOW_INTS, which would
have called the non-returning Scheme handler via SCM_ASYNC_TICK.

This behaviour can be got back by explicitly calling SCM_ASYNC_TICK from
the handler, but I'm not sure if this was what you wanted to avoid with
the posix threads change:

--- scmsigs.c.orig      Tue May  2 20:25:13 2000
+++ scmsigs.c   Tue May  2 20:25:39 2000
@@ -149,6 +149,7 @@
   }
 #endif
   scm_system_async_mark (signal_async);
+  SCM_ASYNC_TICK;
   errno = saved_errno;
 }

guile> (segfault)
standard input:1:1: In procedure segfault in expression (segfault):
standard input:1:1: Bad memory access (Segmentation violation)
ABORT: (signal)

Type "(backtrace)" to get more information.


This also has the advantage of making signal handling fast.  Maybe it
would fail if the segfault occured during a critical section: wrapping
sim_segfault in SCM_ALLOW/DEFER_INTS had no effect, but I'm not sure
why not.

Alternatively, or additionally, something like this could be added:

--- scmsigs.c.orig      Tue May  2 20:25:13 2000
+++ scmsigs.c   Tue May  2 20:31:42 2000
@@ -137,6 +137,11 @@
         the only anomalous path we need to worry about.  */
       SCM_NEWCELL (ignored);
     }
+  /* avoid infinite loop for certain signals if handler returns.  */
+  if (signum == SIGSEGV && got_signal[signum])
+    {
+      raise (signum);
+    }
   got_signal[signum] = 1;
 #if HAVE_SIGACTION
   /* unblock the signal before the scheme handler gets to run, since


which gives the alternative behaviour:

guile> (segfault)
Segmentation fault

which isn't any better than having no handler at all: in the current
guile:

guile> (set-batch-mode?! #t)
guile> (segfault)
Segmentation fault

Reply via email to