diff --git a/src/CHANGELOG b/src/CHANGELOG index 99a45d04e..602e6e0f6 100755 --- a/src/CHANGELOG +++ b/src/CHANGELOG @@ -20,6 +20,9 @@ ECL 10.1.1: - The output values of a process or thread are now collected in the process object and returned by PROCESS-JOIN. + - The interrupt servicing thread must explicitely include the interrupt signal + among the ones it captures. Otherwise it will never be interrupted itself. + ;;; Local Variables: *** ;;; mode:text *** ;;; fill-column:79 *** diff --git a/src/c/threads.d b/src/c/threads.d index fa02dc15b..36256695c 100644 --- a/src/c/threads.d +++ b/src/c/threads.d @@ -121,8 +121,8 @@ thread_cleanup(void *aux) * mp_process_kill(). */ cl_object process = (cl_object)aux; - process->process.active = 0; mp_giveup_lock(process->process.exit_lock); + process->process.active = 0; THREAD_OP_LOCK(); cl_core.processes = ecl_remove_eq(process, cl_core.processes); THREAD_OP_UNLOCK(); diff --git a/src/c/unixint.d b/src/c/unixint.d index 2e16550d7..2c54f3e95 100644 --- a/src/c/unixint.d +++ b/src/c/unixint.d @@ -789,7 +789,7 @@ ecl_interrupt_process(cl_object process, cl_object function) cl_object lock; int ok; function = si_coerce_to_function(function); - lock = mp_get_lock(1, cl_core.signal_queue_lock); + lock = mp_get_lock_wait(cl_core.signal_queue_lock); queue_signal(process->process.env, function); ok = do_interrupt_thread(process); mp_giveup_lock(lock); @@ -901,17 +901,32 @@ asynchronous_signal_servicing_thread() sigset_t handled_set; cl_object signal_code; int signo; + int interrupt_signal = 0; + if (ecl_get_option(ECL_OPT_TRAP_INTERRUPT_SIGNAL)) { + interrupt_signal = ecl_get_option(ECL_OPT_THREAD_INTERRUPT_SIGNAL); + } /* * We wait here for all signals that are blocked in all other * threads. It would be desirable to be able to wait for _all_ - * signals, but this can not be done for SIGFPE, SIGSEGV, etc + * signals, but this can not be done for SIGFPE, SIGSEGV, etc. */ pthread_sigmask(SIG_SETMASK, NULL, &handled_set); + /* + * Under OS X we also have to explicitely add the signal we + * use to communicate process interrupts. For some unknown + * reason those signals may get lost. + */ + if (interrupt_signal) { + sigaddset(&handled_set, interrupt_signal); + pthread_sigmask(SIG_SETMASK, &handled_set, NULL); + } CL_CATCH_ALL_BEGIN(ecl_process_env()) { for (;;) { /* Waiting may fail! */ int status = sigwait(&handled_set, &signo); if (status == 0) { + if (interrupt_signal == signo) + goto RETURN; signal_code = call_handler(lisp_signal_handler, signo, NULL, NULL); if (!Null(signal_code)) { @@ -922,6 +937,7 @@ asynchronous_signal_servicing_thread() } } } CL_CATCH_ALL_END; + RETURN: @(return) } #endif