> 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