From 1964bb94f82d3d81eec3d5797fe875741a9a8182 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Fri, 13 Dec 2013 08:13:49 -0800 Subject: * signal.c (sig_handler): Pass two arguments to signal handler rather than 1. The new argument is the value t, telling the handler that it's asynchronously invoked in a real signal context. If the signal handler returns true, then mark it deferred so that it can re-trigger in a synchronous context. (sig_check): Pass nil as a the second argument to signal handlers, indicating that they are synchronously called, not in a signal handler context. * txr.1: Added documentation. --- ChangeLog | 14 ++++++++++++++ signal.c | 5 +++-- txr.1 | 26 ++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2d87676a..07f901d8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2013-12-13 Kaz Kylheku + + * signal.c (sig_handler): Pass two arguments to signal + handler rather than 1. The new argument is the value t, + telling the handler that it's asynchronously invoked in + a real signal context. If the signal handler returns + true, then mark it deferred so that it can re-trigger + in a synchronous context. + (sig_check): Pass nil as a the second argument to signal handlers, + indicating that they are synchronously called, not + in a signal handler context. + + * txr.1: Added documentation. + 2013-12-13 Kaz Kylheku * signal.c (set_sig_handler): Disable signals around this diff --git a/signal.c b/signal.c index 4a089caf..82f84149 100644 --- a/signal.c +++ b/signal.c @@ -59,7 +59,8 @@ static void sig_handler(int sig) if (lambda) { if (async_sig_enabled) { async_sig_enabled = 0; - funcall1(lambda, num_fast(sig)); + if (funcall2(lambda, num_fast(sig), t)) + sig_deferred |= (1UL << sig); async_sig_enabled = 1; } else { sig_deferred |= (1UL << sig); @@ -191,7 +192,7 @@ val sig_check(void) if ((sd & mask) != 0) { sd &= ~mask; sig_deferred = sd; - funcall1(sig_lambda[i], num_fast(i)); + funcall2(sig_lambda[i], num_fast(i), nil); } } diff --git a/txr.1 b/txr.1 index aeb3abeb..511a1551 100644 --- a/txr.1 +++ b/txr.1 @@ -11142,6 +11142,32 @@ Note that the certain signals like sig-quit and sig-kill cannot be handled. Please observe the signal documentation in the IEEE POSIX standard, and your platform. +A signal handling function must take two arguments. It is of the form: + + (lambda (signal async-p) ...) + +The signal argument is an integer indicating the signal number for which the +handler is being invoked. The asyncp-p argument is a boolean value, nil or t. +If it is t, it indicates that the handler is being invoked +asynchronously---directly in a signal handling context. If it is nil, then it +is a deferred call. Handlers may do more things in a deferred call, such +as terminate by throwing exceptions, and perform I/O. + +The return value of a handler is normally ignored. However if it invoked +asynchronously (the async-p argument is true), then if the handler returns +a true value (any value other than nil), the handler is understood as +requesting that it be deferred. This means that the signal will be marked +as deferred, and handler will be called one more time again at some later +time in a deferred context (async-p nil). This is not guaranteed, however; +it's possible that another signal will arrive before that happens, +possibly resulting in an async call. + +If a handler is invoked synchronously, then its return value is ignored. + +In the current implementation, signals do not queue. If a signal is delivered +to the process again, while it is marked as deferred, it simply stays deferred; +there is no counter associated with a signal, only a boolean flag. + .SS The sig-check function .TP -- cgit v1.2.3