[Ecls-list] Making an external signal handler play nice with embedded ECL
Nils Bruin
nbruin at cecm.sfu.ca
Mon Feb 28 07:12:34 UTC 2011
On Sat, 26 Feb 2011, Juan Jose Garcia-Ripoll wrote:
> In the window from the signal handler swap until ECL is booted, ECL will
> simply discard all signals, because the signal queue is not installed and
> ECL is not marked as booted. Or do you perform the swap every time that ECL
> code is executed?
Yes, we have to perform the swap every time. During ECL code execution, we
need ECLs signal handlers in force (if we enable signals at all) and
during Python code execution, we need the Python handler.
The following might be a solution, if my assumptions on
ecl_disable_interrupts() and ext:with-interrupts are correct.
---------------------------------------------------------------
set_our_sighandlers_to_postpone_signals();
ecl_disable_interrupts();
sigaction(SIGINT,ecl_sigint_handler,NULL);
sigaction(SIGSEGV,ecl_sigsegv_handler,NULL);
/* at this moment, the ecl sighandlers are in force but don't take
action thanks to the disable_interrupts */
result=ecl_eval("
(handler-case
(ext:with-interrupts <actual code here>) ;;interrupts happen here
<condition handling and reporting> ;;and caught and reported here
)");
/* a signal arriving here would still be queued by ECL but won't
be processed for a while */
sigaction(SIGINT,our_sigint_handler,NULL);
sigaction(SIGSEGV,our_sigsegv_handler,NULL);
ecl_clear_interrupts();
/* remove mprotect to avoid unexpected SIGSEGV due to writing env
(we may want to do small ECL operations with interrupts disabled
and hence no need to swap any handlers). Losing a signal here
seems better than risking a SIGSEGV */
ecl_enable_interrupts();
/* this should not be necessary, because on our next trip, we would
disable them before we do anything with ECL anyway. However, if this
is a semaphore that counts enable/disable pairs, then we either
should do it here or just execute ecl_disable_interrupts() one just
after cl_boot(). */
set_our_handlers_to_process_signals();
<process result>
---------------------------------------------------------------
> Your previous suggestion, using some API, looks fine, but it would not work
> with the mprotect() trick, unless your code uses sigaction() and passes the
> appropriate records
Yes. Logically, I think something like the above process needs to happen
anyway. By making our_signal_handler ECL-aware we could perhaps avoid
using the full-blown sigaction to do the swap and we could possibly avoid
the blackout due to the ecl_clear_interrupt.
Comments and suggestions welcome. Also, this might give you some idea for
the hooks required for a possible API for ECL-aware signal handlers.
Question: What would happen if a signal for ECL were queued but no
mprotect were set? Would it take very long before the queue would be
checked? Would the queue be checked at all? If a foreign signal handler
could get away with *just* queueing the signal to ECL, without
mprotect-ing anything, integration would be much easier, because one
doesn't have to deal with the possibility that a signal boomerangs back as
a SIGSEGV (very elegant trick, though!)
More information about the ecl-devel
mailing list