Hi! As 12.12.1 in experimental builds while the unstable/testing one doesn't I've bisected down the changes in upstream git. It seems to work since c7953cc0f54281c3de6a845f3599544afba20b2a. The patch doesn't simply apply to unstable so I haven't tested jet if that'd simply work. Also it's a bit intrusive change done upstream but might give a hiunt for a fix. Also the description sounds like it *could* affect the problem.
Christoph
commit c7953cc0f54281c3de6a845f3599544afba20b2a Author: Juan Jose Garcia Ripoll <jjgar...@users.sourceforge.net> Date: Thu May 17 08:51:26 2012 +0200 Signal handlers receive now an optional keyword argument with the process that received the signal. diff --git a/src/c/main.d b/src/c/main.d index da63f83..29197a4 100644 --- a/src/c/main.d +++ b/src/c/main.d @@ -131,7 +131,9 @@ void ecl_init_env(cl_env_ptr env) { env->c_env = NULL; - +#if !defined(ECL_THREADS) + env->own_process = Cnil; +#endif env->string_pool = Cnil; env->stack = NULL; diff --git a/src/c/symbols_list.h b/src/c/symbols_list.h index a5e87f0..02c1680 100755 --- a/src/c/symbols_list.h +++ b/src/c/symbols_list.h @@ -1950,7 +1950,7 @@ cl_symbols[] = { {EXT_ "WITH-UNIQUE-NAMES", EXT_ORDINARY, NULL, -1, OBJNULL}, -{SYS_ "HANDLE-SIGNAL", SI_ORDINARY, si_handle_signal, 1, OBJNULL}, +{SYS_ "HANDLE-SIGNAL", SI_ORDINARY, si_handle_signal, 2, OBJNULL}, {EXT_ "WITH-INTERRUPTS", MP_CONSTANT, NULL, -1, OBJNULL}, {EXT_ "WITHOUT-INTERRUPTS", MP_CONSTANT, NULL, -1, OBJNULL}, diff --git a/src/c/unixint.d b/src/c/unixint.d index 18b0e04..a27e9da 100755 --- a/src/c/unixint.d +++ b/src/c/unixint.d @@ -321,7 +321,7 @@ unblock_signal(cl_env_ptr the_env, int signal) ecl_def_ct_base_string(str_ignore_signal,"Ignore signal",13,static,const); static void -handle_signal_now(cl_object signal_code) +handle_signal_now(cl_object signal_code, cl_object process) { switch (type_of(signal_code)) { case t_fixnum: @@ -336,6 +336,10 @@ handle_signal_now(cl_object signal_code) */ if (cl_find_class(2, signal_code, Cnil) != Cnil) cl_cerror(2, str_ignore_signal, signal_code); +#ifdef ECL_THREADS + else if (!Null(process)) + _ecl_funcall3(signal_code, @':process', process); +#endif else _ecl_funcall1(signal_code); break; @@ -351,9 +355,9 @@ handle_signal_now(cl_object signal_code) } cl_object -si_handle_signal(cl_object signal_code) +si_handle_signal(cl_object signal_code, cl_object process) { - handle_signal_now(signal_code); + handle_signal_now(signal_code, process); @(return) } @@ -361,7 +365,7 @@ static void handle_all_queued(cl_env_ptr env) { while (env->pending_interrupt != Cnil) { - handle_signal_now(pop_signal(env)); + handle_signal_now(pop_signal(env), env->own_process); } } @@ -436,7 +440,7 @@ handle_or_queue(cl_env_ptr the_env, cl_object signal_code, int code) else { if (code) unblock_signal(the_env, code); si_trap_fpe(@'last', Ct); /* Clear FPE exception flag */ - handle_signal_now(signal_code); + handle_signal_now(signal_code, the_env->own_process); } } @@ -472,11 +476,112 @@ handler_fn_prototype(evil_signal_handler, int sig, siginfo_t *siginfo, void *dat signal_object = ecl_gethash_safe(MAKE_FIXNUM(sig), cl_core.known_signals, Cnil); - handle_signal_now(signal_object); + handle_signal_now(signal_object, the_env->own_process); errno = old_errno; } #if defined(ECL_THREADS) && !defined(ECL_MS_WINDOWS_HOST) +typedef struct { + cl_object process; + int signo; +} signal_thread_message; +static cl_object signal_thread_process = Cnil; +static signal_thread_message signal_thread_msg; +static cl_object signal_thread_spinlock = Cnil; +static int signal_thread_pipe[2] = {-1,-1}; + +static void +handler_fn_prototype(deferred_signal_handler, int sig, siginfo_t *siginfo, void *data) +{ + int old_errno = errno; + cl_env_ptr the_env; + signal_thread_message msg; + reinstall_signal(sig, deferred_signal_handler); + /* The lisp environment might not be installed. */ + the_env = ecl_process_env(); + unlikely_if (zombie_process(the_env)) + return; + msg.signo = sig; + msg.process = the_env->own_process; + if (msg.process == signal_thread_process) { + /* The signal handling thread may also receive signals. In + * this case we do not use the pipe, but just copy the message + * Note that read() will abort the thread will get notified. */ + signal_thread_msg = msg; + } else if (signal_thread_pipe[1] > 0) { + ecl_get_spinlock(the_env, &signal_thread_spinlock); + write(signal_thread_pipe[1], &msg, sizeof(msg)); + ecl_giveup_spinlock(&signal_thread_spinlock); + } else { + /* Nothing to do. There is no way to handle this signal because + * the responsible thread is not running */ + } + errno = old_errno; +} + +static cl_object +asynchronous_signal_servicing_thread() +{ + const cl_env_ptr the_env = ecl_process_env(); + int interrupt_signal; + /* + * We block all signals except the usual interrupt thread. + */ + { + sigset_t handled_set; + sigfillset(&handled_set); + if (ecl_option_values[ECL_OPT_TRAP_INTERRUPT_SIGNAL]) { + interrupt_signal = + ecl_option_values[ECL_OPT_THREAD_INTERRUPT_SIGNAL]; + sigdelset(&handled_set, interrupt_signal); + } + pthread_sigmask(SIG_BLOCK, &handled_set, NULL); + } + /* + * We create the object for communication. We need a lock to prevent other + * threads from writing before the pipe is created. + */ + ecl_get_spinlock(the_env, &signal_thread_spinlock); + pipe(signal_thread_pipe); + ecl_giveup_spinlock(&signal_thread_spinlock); + signal_thread_msg.process = Cnil; + for (;;) { + cl_object signal_code; + signal_thread_msg.process = Cnil; + if (read(signal_thread_pipe[0], &signal_thread_msg, + sizeof(signal_thread_msg)) < 0) + { + if (errno != EINTR || + signal_thread_msg.process != the_env->own_process) + break; + } + if (signal_thread_msg.signo == interrupt_signal && + signal_thread_msg.process == the_env->own_process) { + break; + } +#ifdef SIGCHLD + if (signal_thread_msg.signo == SIGCHLD) { + si_wait_for_all_processes(); + continue; + } +#endif + signal_code = ecl_gethash_safe(MAKE_FIXNUM(signal_thread_msg.signo), + cl_core.known_signals, + Cnil); + if (!Null(signal_code)) { + mp_process_run_function(4, @'si::handle-signal', + @'si::handle-signal', + signal_code, + signal_thread_msg.process); + } + } + close(signal_thread_pipe[0]); + close(signal_thread_pipe[1]); + ecl_return0(the_env); +} +#endif /* ECL_THREADS && !ECL_MS_WINDOWS_HOST */ + +#if defined(ECL_THREADS) && !defined(ECL_MS_WINDOWS_HOST) static void handler_fn_prototype(process_interrupt_handler, int sig, siginfo_t *siginfo, void *data) { @@ -582,7 +687,7 @@ handler_fn_prototype(fpe_signal_handler, int sig, siginfo_t *info, void *data) */ si_trap_fpe(@'last', Ct); /* Clear FPE exception flag */ unblock_signal(the_env, code); - handle_signal_now(condition); + handle_signal_now(condition, the_env->own_process); /* We will not reach past this point. */ } @@ -945,7 +1050,7 @@ _ecl_w32_exception_filter(struct _EXCEPTION_POINTERS* ep) cl_object signal = pop_signal(the_env); process->process.interrupt = Cnil; while (signal != Cnil && signal) { - handle_signal_now(signal); + handle_signal_now(signal, the_env->own_process); signal = pop_signal(the_env); } return EXCEPTION_CONTINUE_EXECUTION; @@ -953,37 +1058,37 @@ _ecl_w32_exception_filter(struct _EXCEPTION_POINTERS* ep) } /* Catch all arithmetic exceptions */ case EXCEPTION_INT_DIVIDE_BY_ZERO: - handle_signal_now(@'division-by-zero'); + handle_signal_now(@'division-by-zero', the_env->own_process); return EXCEPTION_CONTINUE_EXECUTION; case EXCEPTION_INT_OVERFLOW: - handle_signal_now(@'arithmetic-error'); + handle_signal_now(@'arithmetic-error', the_env->own_process); return EXCEPTION_CONTINUE_EXECUTION; case EXCEPTION_FLT_DIVIDE_BY_ZERO: - handle_signal_now(@'floating-point-overflow'); + handle_signal_now(@'floating-point-overflow', the_env->own_process); return EXCEPTION_CONTINUE_EXECUTION; case EXCEPTION_FLT_OVERFLOW: - handle_signal_now(@'floating-point-overflow'); + handle_signal_now(@'floating-point-overflow', the_env->own_process); return EXCEPTION_CONTINUE_EXECUTION; case EXCEPTION_FLT_UNDERFLOW: - handle_signal_now(@'floating-point-underflow'); + handle_signal_now(@'floating-point-underflow', the_env->own_process); return EXCEPTION_CONTINUE_EXECUTION; case EXCEPTION_FLT_INEXACT_RESULT: - handle_signal_now(@'floating-point-inexact'); + handle_signal_now(@'floating-point-inexact', the_env->own_process); return EXCEPTION_CONTINUE_EXECUTION; case EXCEPTION_FLT_DENORMAL_OPERAND: case EXCEPTION_FLT_INVALID_OPERATION: - handle_signal_now(@'floating-point-invalid-operation'); + handle_signal_now(@'floating-point-invalid-operation', the_env->own_process); return EXCEPTION_CONTINUE_EXECUTION; case EXCEPTION_FLT_STACK_CHECK: - handle_signal_now(@'arithmetic-error'); + handle_signal_now(@'arithmetic-error', the_env->own_process); return EXCEPTION_CONTINUE_EXECUTION; /* Catch segmentation fault */ case EXCEPTION_ACCESS_VIOLATION: - handle_signal_now(@'ext::segmentation-violation'); + handle_signal_now(@'ext::segmentation-violation', the_env->own_process); return EXCEPTION_CONTINUE_EXECUTION; /* Catch illegal instruction */ case EXCEPTION_ILLEGAL_INSTRUCTION: - handle_signal_now(@'ext::illegal-instruction'); + handle_signal_now(@'ext::illegal-instruction', the_env->own_process); return EXCEPTION_CONTINUE_EXECUTION; /* Do not catch anything else */ default: @@ -999,9 +1104,9 @@ static cl_object W32_handle_in_new_thread(cl_object signal_code) { int outside_ecl = ecl_import_current_thread(@'si::handle-signal', Cnil); - mp_process_run_function(3, @'si::handle-signal', + mp_process_run_function(4, @'si::handle-signal', @'si::handle-signal', - signal_code); + signal_code, Cnil); if (outside_ecl) ecl_release_current_thread(); } @@ -1021,7 +1126,7 @@ BOOL WINAPI W32_console_ctrl_handler(DWORD type) } #endif /* ECL_WINDOWS_THREADS */ -#if defined(ECL_THREADS) && defined(HAVE_SIGPROCMASK) +#if 0 static cl_object asynchronous_signal_servicing_thread() { @@ -1155,8 +1260,8 @@ install_asynchronous_signal_handlers() #else # if defined(ECL_THREADS) && defined(HAVE_SIGPROCMASK) # define async_handler(signal,handler,mask) { \ - if (ecl_option_values[ECL_OPT_SIGNAL_HANDLING_THREAD]) { \ - sigaddset(mask, signal); \ + if (ecl_option_values[ECL_OPT_SIGNAL_HANDLING_THREAD]) { \ + mysignal(signal, deferred_signal_handler); \ } else { \ mysignal(signal,handler); \ }} @@ -1221,6 +1326,7 @@ install_signal_handling_thread() Cnil, 0); cl_object process = + signal_thread_process = mp_process_run_function_wait(2, @'si::signal-servicing', fun); diff --git a/src/h/external.h b/src/h/external.h index 57581da..c4dc09d 100755 --- a/src/h/external.h +++ b/src/h/external.h @@ -94,9 +94,7 @@ struct cl_env_struct { BIGNUM_REGISTER_SIZE in config.h */ cl_object big_register[3]; -#ifdef ECL_THREADS cl_object own_process; -#endif cl_object pending_interrupt; cl_object signal_queue; cl_object signal_queue_spinlock; @@ -1868,7 +1866,7 @@ extern ECL_API cl_object si_copy_file(cl_object orig, cl_object end); #define ecl_enable_interrupts() ecl_enable_interrupts_env(&cl_env) #define ECL_PSEUDO_ATOMIC_ENV(env,stmt) (ecl_disable_interrupts_env(env),(stmt),ecl_enable_interrupts_env(env)) #define ECL_PSEUDO_ATOMIC(stmt) (ecl_disable_interrupts(),(stmt),ecl_enable_interrupts()) -extern ECL_API cl_object si_handle_signal(cl_object signal); +extern ECL_API cl_object si_handle_signal(cl_object signal, cl_object process); extern ECL_API cl_object si_get_signal_handler(cl_object signal); extern ECL_API cl_object si_set_signal_handler(cl_object signal, cl_object handler); extern ECL_API cl_object si_catch_signal(cl_narg narg, cl_object signal, cl_object state, ...); diff --git a/src/lsp/top.lsp b/src/lsp/top.lsp index b6e43a3..9857dde 100644 --- a/src/lsp/top.lsp +++ b/src/lsp/top.lsp @@ -498,7 +498,7 @@ Use special code 0 to cancel this operation.") (restart-case (simple-terminal-interrupt) (continue ()))) -(defun terminal-interrupt (&optional (correctablep t)) +(defun terminal-interrupt (&key process (correctablep t)) (declare (ignore correctablep)) #+threads (mp:without-interrupts