[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