This is the mail archive of the
guile@cygnus.com
mailing list for the Guile project.
Re: Guile and alarm(2)
Jim Blandy <jimb@red-bean.com> writes:
> > What happens when Guile is in the middle of some processing
> > (gh_eval_str, or something) and the process is interrupted by a
> > signal, e.g. SIGALRM?
>
> This is an area I'm not expert in myself, but reading the code and
> some experimentation with GDB suggest:
> - Guile sets all system calls to be restarted on signals. That is, it
> sets the SA_RESTART flag on each signal.
> - The interaction loop establishes handlers for SIGINT, SIGFPE,
> SIGBUS, and SIGSEGV.
>
> Aside from that, signal handling proceeds as normal.
>
> > The reason i'm asking this is that in Apache, one can set hard
> > timeouts, which work by calling alarm(2), and aborting all
> > processing. I'm sure that at least in those areas who are usually
> > secured by SCM_DEFER_INTS / SCM_ALLOW_INTS, such an interrupt
> > (without resumeing the original processing) would cause alot of
> > trouble. Right?
>
> Yes. You will have some problems if you try to simply abort out of
> arbitrary Guile code. The garbage collector, for instance.
>
> Does Apache provide any way for modules to establish a little more
> control over this? Surely Guile is not the only module that isn't
> safe to interrupt at arbitrary times. Anything that maintains
> non-trivial data structures which could be left in an inconsistent
> state or allocates memory would have this problem, I'd think.
>
> The solution will involve marking an async for SIGALRM, and then allowing
> Guile to continue to run until the next safe interruption point, where
> it will jump to a SIGALRM handler. At this point, you can abort the
> call.
It's actually simpler than that from the user's point of view. All
signals with Scheme level handlers are delayed until the end of
SCM_DEFER_INTS / SCM_ALLOW_INTS blocks. So, if you install your
handler using scm_sigaction (can be made both from Scheme and C),
you're safe.
The mechanism is that scm_sigaction installs take_signal as a proxy
handler. take_signal marks the signal_async which will invoke the
real handler at the end of the critical section.