From 20df3c699542dc239f5db546b7b51b9dd60860dd Mon Sep 17 00:00:00 2001 From: Javier Sagredo Date: Fri, 29 May 2026 02:44:36 +0200 Subject: [PATCH] Make tcp_accept poll INTERRUPT --- src/machine/system_calls.rs | 39 ++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index f66d7c32..68e3f79e 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -7127,7 +7127,44 @@ impl Machine { (HeapCellValueTag::Cons, cons_ptr) => { match_untyped_arena_ptr!(cons_ptr, (ArenaHeaderTag::TcpListener, tcp_listener) => { - match tcp_listener.accept().ok() { + // Poll accept() in non-blocking mode so that a SIGINT + // delivered while we're waiting actually lands as a + // catchable '$interrupt_thrown' exception in Prolog, + // instead of being stuck behind a blocking syscall. + let _ = tcp_listener.set_nonblocking(true); + let accepted: Option<_> = 'poll: loop { + match tcp_listener.accept() { + Ok(pair) => break 'poll Some(pair), + Err(ref e) if e.kind() == ErrorKind::WouldBlock => { + let interrupted = machine::INTERRUPT.load( + std::sync::atomic::Ordering::Relaxed); + if interrupted + && machine::INTERRUPT.compare_exchange( + true, + false, + std::sync::atomic::Ordering::Relaxed, + std::sync::atomic::Ordering::Relaxed, + ).is_ok() + { + let _ = tcp_listener.set_nonblocking(false); + // Return an Err so the dispatch site's + // try_or_throw! macro performs the throw + // + backtrack + continue dance correctly + // (calling throw+backtrack here and then + // returning Ok(()) would let the dispatch + // step over the unwound program counter + // with step_or_fail!). + let err = self.machine_st.interrupt_error(); + let src = functor_stub(atom!("repl"), 0); + return Err(self.machine_st.error_form(err, src)); + } + std::thread::sleep(std::time::Duration::from_millis(100)); + } + Err(_) => break 'poll None, + } + }; + let _ = tcp_listener.set_nonblocking(false); + match accepted { Some((tcp_stream, socket_addr)) => { let client = AtomTable::build_with(&self.machine_st.atom_tbl, &socket_addr.to_string()); -- 2.54.0