As noted above it is not possible to call e.g. SP_query()
or
even SP_event()
from an arbitrary signal handler. That is, from
signal handlers installed with signal
or
sigaction
. Instead you need to install the signal handler using
SP_signal()
.
When the OS delivers a signal sig
for which
SP_signal(sig,func)
has been called SICStus will not call
func
immediately. Instead the call to func
will be delayed
until it is safe for Prolog to do so, in much the same way that functions
installed by SP_event()
are handled (this is an incompatible change
from SICStus 3.8 and earlier).
Since the signal handling function func
will not be called
immediately upon delivery of the signal to the process it only makes
sense to use SP_signal()
to handle certain asynchronous signals
such as SIGINT
, SIGUSR1
, SIGUSR2
. Other
asynchronous signals handled specially by the OS, such as SIGCHLD
are not suitable for handling via SP_signal()
. Note that the
development system installs a handler for `SIGINT', and, under
Windows, `SIGBREAK', to catch keyboard interrupts. Under UNIX,
library(timeout)
currently uses SIGVTALRM
.
When func
is called it may only call other (non SICStus) C code
and SP_event()
. Note that func
will be called in the main
thread.
To install a function, func
, as a handler for the signal
sig
, call:
typedef void SP_SigFun (int); SP_SigFun SP_signal (int sig, SP_SigFun fun);
SP_signal()
returns SP_SIG_ERR
on error. On success,
SP_signal()
returns some unspecified value different from SP_SIG_ERR
.
If fun
is one of the special constants SP_SIG_IGN
or
SP_SIG_DFL
, then one of two things happens. If a signal handler
for sig
has already been installed with SP_signal()
, then the
SICStus OS-level signal handler is removed and replaced with,
respectively, SIG_IGN
or SIG_DFL
. If a signal handler has
not been installed with SP_signal()
, then SP_signal()
does
nothing and returns SP_SIG_ERR
.
A signal handler installed by a foreign resource should be
uninstalled in the deinit function for the foreign
resource. This is to prevent the handler in the foreign resource
from being called after the code of the foreign resource has been
unloaded (e.g. by unload_foreign_resource/1
).
The following two functions were used prior to SICStus 3., but are obsolete now:
SP_SigFun SP_reinstall_signal (int sig, SP_SigFun) obsolescent void SP_continue(void) obsolescent
they are no-ops.
The following piece of C code illustrates these facilities. The
function signal_init()
installs the function
signal_handler()
as the primary signal handler for the signals
SIGUSR1
and SIGUSR2
. That function invokes the
predicate user:prolog_handler/1
as the actual signal
handler, passing the signal number as an argument to the
predicate.
SP_pred_ref event_pred; static int signal_event(void *handle) { int signal_no = (int) handle; SP_term_ref x=SP_new_term_ref(); int rc; SP_put_integer(x, signal_no); /* Should not give an error */ rc = SP_query(event_pred, x); if (rc == SP_ERROR && SP_exception_term(x)) SP_raise_exception(x); /* Propagate any raised exception */ return rc; } static void signal_handler(int signal_no) { /* cast to size_t to avoid warnings on 64-bit machines */ SP_event(signal_event, (void *)(size_t)signal_no); /* The two calls below are for SICStus 3.8 compatibility */ SP_reinstall_signal(signal_no, signal_handler); SP_continue(); } void signal_init(void) { event_pred = SP_predicate("prolog_handler",1,"user"); SP_signal(SIGUSR1, signal_handler); SP_signal(SIGUSR2, signal_handler); }