summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2013-12-13 08:13:49 -0800
committerKaz Kylheku <kaz@kylheku.com>2013-12-13 08:13:49 -0800
commit1964bb94f82d3d81eec3d5797fe875741a9a8182 (patch)
tree445c44f7caf3e3ced5d9dd46e89db6c9a75ca802
parenta846f5e378a1c03ae122c711308899bbe381a7f1 (diff)
downloadtxr-1964bb94f82d3d81eec3d5797fe875741a9a8182.tar.gz
txr-1964bb94f82d3d81eec3d5797fe875741a9a8182.tar.bz2
txr-1964bb94f82d3d81eec3d5797fe875741a9a8182.zip
* 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.
-rw-r--r--ChangeLog14
-rw-r--r--signal.c5
-rw-r--r--txr.126
3 files changed, 43 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index 2d87676a..07f901d8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,19 @@
2013-12-13 Kaz Kylheku <kaz@kylheku.com>
+ * 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 <kaz@kylheku.com>
+
* signal.c (set_sig_handler): Disable signals around this
function because it manipulates the mask of deferred
signals which can also be manipulated by an async signal.
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