| 1 | % (c) 2011-2015 Lehrstuhl fuer Softwaretechnik und Programmiersprachen, | |
| 2 | % Heinrich Heine Universitaet Duesseldorf | |
| 3 | % This software is licenced under EPL 1.0 (http://www.eclipse.org/org/documents/epl-v10.html) | |
| 4 | ||
| 5 | :- module(user_signal, [ user_interruptable_call_det/2 | |
| 6 | , protect_from_user_interrupt_det/1 | |
| 7 | , ignore_user_interrupt_det/1 | |
| 8 | , get_user_signal_ref/1]). | |
| 9 | ||
| 10 | :- use_module('../../src/module_information.pl'). | |
| 11 | ||
| 12 | :- module_info(group,infrastructure). | |
| 13 | :- module_info(description,'This is the interface to C code for interrupting Prolog runs with a UNIX signal.'). | |
| 14 | ||
| 15 | :- meta_predicate user_interruptable_call_det(0,-). | |
| 16 | :- meta_predicate protect_from_user_interrupt_det(0). | |
| 17 | :- meta_predicate ignore_user_interrupt_det(0). | |
| 18 | ||
| 19 | :- load_files(library(system), [when(compile_time), imports([environ/2])]). | |
| 20 | :- if(environ(no_interrupts,true)). | |
| 21 | % turn off user interrupt handling: ctrl-c jumps into Prolog debugger | |
| 22 | ||
| 23 | user_interruptable_call_det(Call,Result) :- call(Call), Result=ok. | |
| 24 | ignore_user_interrupt_det(Call) :- call(Call). | |
| 25 | protect_from_user_interrupt_det(Call) :- call(Call). | |
| 26 | get_user_signal_ref(off). | |
| 27 | ||
| 28 | :- else. | |
| 29 | foreign_resource(user_signal, [set_user_signal_mode,get_user_signal_mode,user_signal_init,get_user_sig_reference]). | |
| 30 | foreign(user_signal_init, user_signal_init). | |
| 31 | foreign(set_user_signal_mode, set_user_signal_mode(+integer,+integer)). | |
| 32 | foreign(get_user_signal_mode, get_user_signal_mode([-integer])). | |
| 33 | foreign(get_user_sig_reference, get_user_sig_reference([-integer])). | |
| 34 | ||
| 35 | :- dynamic loaded/0. | |
| 36 | ||
| 37 | init_user_signal :- loadfr. | |
| 38 | ||
| 39 | loadfr :- | |
| 40 | ( loaded -> true | |
| 41 | ; otherwise -> | |
| 42 | load_foreign_resource(library(user_signal)), | |
| 43 | user_signal_init, | |
| 44 | %write(user_signal_int),nl, | |
| 45 | assert(loaded)). | |
| 46 | ||
| 47 | :- meta_predicate catch_interrupt_exception(0,-). | |
| 48 | catch_interrupt_exception(Call,Result) :- | |
| 49 | catch( call(Call), | |
| 50 | E, | |
| 51 | ( E==user_interrupt_signal -> Result=interrupted | |
| 52 | ; otherwise -> throw(E))), | |
| 53 | ( Result == interrupted -> true | |
| 54 | ; otherwise -> Result=ok). | |
| 55 | ||
| 56 | %% user_interruptable_call_det(Call,Result) :- !,call(Call), Result=ok. % comment in to turn off CTRL-C | |
| 57 | user_interruptable_call_det(Call,Result) :- | |
| 58 | loadfr, | |
| 59 | get_user_signal_mode(Mode), | |
| 60 | call_cleanup( (set_user_signal_mode(1,2), | |
| 61 | catch_interrupt_exception(Call,Result),!), | |
| 62 | set_user_signal_mode(1,Mode)). | |
| 63 | ||
| 64 | %% protect_from_user_interrupt_det(Call) :- !. % comment in to turn off CTRL-C | |
| 65 | protect_from_user_interrupt_det(Call) :- | |
| 66 | loadfr, | |
| 67 | get_user_signal_mode(Mode), | |
| 68 | call_cleanup( (set_user_signal_mode(0,1), call(Call), !), | |
| 69 | set_user_signal_mode(1,Mode)). | |
| 70 | ||
| 71 | ignore_user_interrupt_det(Call) :- | |
| 72 | loadfr, | |
| 73 | get_user_signal_mode(Mode), | |
| 74 | call_cleanup( (set_user_signal_mode(0,0), call(Call), !), | |
| 75 | set_user_signal_mode(0,Mode)). | |
| 76 | ||
| 77 | get_user_signal_ref(Ref) :- | |
| 78 | loadfr, | |
| 79 | get_user_sig_reference(Ref). | |
| 80 | :- endif. |