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, on Windows, SIGBREAK
, to catch keyboard interrupts. On 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) { SP_event(signal_event, (void *)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); }