From: Mark Thom Date: Mon, 30 Sep 2019 19:27:22 +0000 (-0600) Subject: return to toplevel from a long running query after receiving Ctrl-C X-Git-Tag: v0.8.110~33 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=b26c5c213ee60c380bd6f2ac20184e225bd90a47;p=scryer-prolog.git return to toplevel from a long running query after receiving Ctrl-C --- diff --git a/Cargo.toml b/Cargo.toml index cf68711d..b9d6df85 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,9 @@ indexmap = "1.0.2" dirs = "2.0.2" downcast = "0.10.0" indexmap = "1.0.2" +lazy_static = "1.4.0" +libc = "0.2.62" +nix = "0.15.0" ordered-float = "0.5.0" prolog_parser = "0.8.30" ref_thread_local = "0.0.0" diff --git a/src/main.rs b/src/main.rs index 4530d63b..304c7e89 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,20 +2,38 @@ extern crate downcast; extern crate indexmap; #[macro_use] +extern crate lazy_static; +extern crate libc; +extern crate nix; +#[macro_use] extern crate prolog_parser; #[macro_use] extern crate ref_thread_local; extern crate termion; +use nix::sys::signal; + mod prolog; use prolog::machine::*; use prolog::read::*; +use std::sync::atomic::Ordering; + #[cfg(test)] mod tests; +extern fn handle_sigint(signal: libc::c_int) { + let signal = signal::Signal::from_c_int(signal).unwrap(); + if signal == signal::Signal::SIGINT { + INTERRUPT.store(true, Ordering::Relaxed); + } +} + fn main() { - let mut wam = Machine::new(readline::input_stream()); + let handler = signal::SigHandler::Handler(handle_sigint); + unsafe { signal::signal(signal::Signal::SIGINT, handler) }.unwrap(); + + let mut wam = Machine::new(readline::input_stream()); wam.run_top_level(); } diff --git a/src/prolog/machine/machine_state_impl.rs b/src/prolog/machine/machine_state_impl.rs index ac737a7e..836742bb 100644 --- a/src/prolog/machine/machine_state_impl.rs +++ b/src/prolog/machine/machine_state_impl.rs @@ -8,6 +8,7 @@ use prolog::forms::*; use prolog::heap_iter::*; use prolog::heap_print::*; use prolog::instructions::*; +use prolog::machine::INTERRUPT; use prolog::machine::and_stack::*; use prolog::machine::attributed_variables::*; use prolog::machine::code_repo::CodeRepo; @@ -3176,6 +3177,13 @@ impl MachineState { lco: bool, use_default_cp: bool, ) { + let interrupted = INTERRUPT.load(std::sync::atomic::Ordering::Relaxed); + + if INTERRUPT.compare_and_swap(interrupted, false, std::sync::atomic::Ordering::Relaxed) { + self.fail = true; + return; + } + let mut default_call_policy: Box = Box::new(DefaultCallPolicy {}); let call_policy = if use_default_cp { &mut default_call_policy diff --git a/src/prolog/machine/mod.rs b/src/prolog/machine/mod.rs index a1a228fa..ece7bbea 100644 --- a/src/prolog/machine/mod.rs +++ b/src/prolog/machine/mod.rs @@ -46,6 +46,7 @@ use std::io::{stdout, Read, Write}; use std::mem; use std::ops::Index; use std::rc::Rc; +use std::sync::atomic::AtomicBool; use termion::raw::IntoRawMode; @@ -54,6 +55,10 @@ pub struct MachinePolicies { cut_policy: Box, } +lazy_static! { + pub static ref INTERRUPT: AtomicBool = AtomicBool::new(false); +} + impl MachinePolicies { #[inline] fn new() -> Self {