Is there a way to 'trap' (e.g. 'catch') an operating system signal within GNU Prolog? (I'm using Ubuntu/Linux, latest gprolog).
I think a long time ago I used this approach in WAMCC, before that morphed into GNU Prolog:
:- catch(Long_Running_Goal,signal(2),write('program interrupted'))
But if I test this using a (repeat,fail) infinite loop with, for example
:- catch((repeat,fail),X,write(X)).
In the interpreter Ctrl-C still takes me to the trace/debugger, and the compiled program just quits if I interrupt it with kill -1
, kill -2
etc.
I've tried compiling the program with --no-top-level
in case the default toplevel somehow captures the signal, but that made no difference.
SWI-Prolog seems to have a suitable built-in predicate on_signal
which serves the purpose but I'm looking for a solution with gprolog if that's possible.
Thanks to mescalinum who confirmed signal handling is not available by default in GNU Prolog.
But GNU Prolog has excellent support for user routines in C, and I've been able to write a small amount of C code which catches the Linux signal and triggers (if required) a Prolog exception (note mine is Ubuntu 14.04/GNU Prolog 1.3.0 so C type for
init_signal
function isBool
from gprolog.h - this changed in gprolog.h 1.3.1 onwards toPlBool
- see 1.3.0 vs most recent manuals):C code "signal.c":
Test usage in Prolog "test.pl" - the "long-running" query in this example is o_query, used in a 'catch' relation and can be interrupted with SIGHUP:
Compile with
gplc test.pl signal.c
Now if the program is run with ./test it can be interrupted from another terminal with
kill -1 <test process id>
For my purposes, I can usefully handle the incoming exception while I'm in the C signal handler, but reflecting it back to a Prolog 'throw' (in this case with a 'instantiation error') keeps the code tidily within Prolog.
The reason I want to be able to send (and catch) a signal to the executing GNU Prolog process is because my system is a high-performance parallel processing Prolog environment which can trigger any long-running Prolog process to dynamically 'split' itself into multiple parts which then execute on other machines. But you fundamentally cannot (with my method) predict the exact distribution of work and in due course other processors will be interrupted (i.e. sent a signal) to further split the workload.