handle interrupts for tcp server
This commit is contained in:
@@ -4723,6 +4723,36 @@ impl Machine {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn interrupt_occured(&mut self) -> bool {
|
||||||
|
let interrupted = machine::INTERRUPT.load(std::sync::atomic::Ordering::Relaxed);
|
||||||
|
|
||||||
|
match machine::INTERRUPT.compare_exchange(
|
||||||
|
interrupted,
|
||||||
|
false,
|
||||||
|
std::sync::atomic::Ordering::Relaxed,
|
||||||
|
std::sync::atomic::Ordering::Relaxed,
|
||||||
|
) {
|
||||||
|
Ok(interruption) => {
|
||||||
|
if interruption {
|
||||||
|
self.machine_st.throw_interrupt_exception();
|
||||||
|
self.machine_st.backtrack();
|
||||||
|
// We have extracted control over the Tokio runtime to the calling context for enabling library use case
|
||||||
|
// (see https://github.com/mthom/scryer-prolog/pull/1880)
|
||||||
|
// So we only have access to a runtime handle in here and can't shut it down.
|
||||||
|
// Since I'm not aware of the consequences of deactivating this new code which came in while PR 1880
|
||||||
|
// was not merged, I'm only deactivating it for now.
|
||||||
|
//let old_runtime = std::mem::replace(&mut self.runtime, tokio::runtime::Runtime::new().unwrap());
|
||||||
|
//old_runtime.shutdown_background();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(_) => unreachable!(),
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "http")]
|
#[cfg(feature = "http")]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn http_accept(&mut self) -> CallResult {
|
pub(crate) fn http_accept(&mut self) -> CallResult {
|
||||||
@@ -4822,29 +4852,8 @@ impl Machine {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
Err(std::sync::mpsc::RecvTimeoutError::Timeout) => {
|
Err(std::sync::mpsc::RecvTimeoutError::Timeout) => {
|
||||||
let interrupted = machine::INTERRUPT.load(std::sync::atomic::Ordering::Relaxed);
|
if self.interrupt_occured() {
|
||||||
|
break;
|
||||||
match machine::INTERRUPT.compare_exchange(
|
|
||||||
interrupted,
|
|
||||||
false,
|
|
||||||
std::sync::atomic::Ordering::Relaxed,
|
|
||||||
std::sync::atomic::Ordering::Relaxed,
|
|
||||||
) {
|
|
||||||
Ok(interruption) => {
|
|
||||||
if interruption {
|
|
||||||
self.machine_st.throw_interrupt_exception();
|
|
||||||
self.machine_st.backtrack();
|
|
||||||
// We have extracted control over the Tokio runtime to the calling context for enabling library use case
|
|
||||||
// (see https://github.com/mthom/scryer-prolog/pull/1880)
|
|
||||||
// So we only have access to a runtime handle in here and can't shut it down.
|
|
||||||
// Since I'm not aware of the consequences of deactivating this new code which came in while PR 1880
|
|
||||||
// was not merged, I'm only deactivating it for now.
|
|
||||||
//let old_runtime = std::mem::replace(&mut self.runtime, tokio::runtime::Runtime::new().unwrap());
|
|
||||||
//old_runtime.shutdown_background();
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(_) => unreachable!(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
@@ -7105,6 +7114,7 @@ impl Machine {
|
|||||||
let (tcp_listener, port): (TypedArenaPtr<TcpListener>, _) =
|
let (tcp_listener, port): (TypedArenaPtr<TcpListener>, _) =
|
||||||
match TcpListener::bind(server_addr).map_err(|e| e.kind()) {
|
match TcpListener::bind(server_addr).map_err(|e| e.kind()) {
|
||||||
Ok(tcp_listener) => {
|
Ok(tcp_listener) => {
|
||||||
|
let _ = tcp_listener.set_nonblocking(true);
|
||||||
let port = tcp_listener.local_addr().map(|addr| addr.port()).ok();
|
let port = tcp_listener.local_addr().map(|addr| addr.port()).ok();
|
||||||
|
|
||||||
if let Some(port) = port {
|
if let Some(port) = port {
|
||||||
@@ -7170,12 +7180,14 @@ impl Machine {
|
|||||||
|
|
||||||
let culprit = self.deref_register(1);
|
let culprit = self.deref_register(1);
|
||||||
|
|
||||||
|
use std::io::ErrorKind;
|
||||||
read_heap_cell!(culprit,
|
read_heap_cell!(culprit,
|
||||||
(HeapCellValueTag::Cons, cons_ptr) => {
|
(HeapCellValueTag::Cons, cons_ptr) => {
|
||||||
match_untyped_arena_ptr!(cons_ptr,
|
match_untyped_arena_ptr!(cons_ptr,
|
||||||
(ArenaHeaderTag::TcpListener, tcp_listener) => {
|
(ArenaHeaderTag::TcpListener, tcp_listener) => {
|
||||||
match tcp_listener.accept().ok() {
|
loop {
|
||||||
Some((tcp_stream, socket_addr)) => {
|
match tcp_listener.accept() {
|
||||||
|
Ok((tcp_stream, socket_addr)) => {
|
||||||
let client = AtomTable::build_with(&self.machine_st.atom_tbl, &socket_addr.to_string());
|
let client = AtomTable::build_with(&self.machine_st.atom_tbl, &socket_addr.to_string());
|
||||||
|
|
||||||
let mut tcp_stream = Stream::from_tcp_stream(
|
let mut tcp_stream = Stream::from_tcp_stream(
|
||||||
@@ -7198,11 +7210,22 @@ impl Machine {
|
|||||||
|
|
||||||
self.machine_st.bind(client_addr.as_var().unwrap(), client);
|
self.machine_st.bind(client_addr.as_var().unwrap(), client);
|
||||||
self.machine_st.bind(stream_addr.as_var().unwrap(), tcp_stream.into());
|
self.machine_st.bind(stream_addr.as_var().unwrap(), tcp_stream.into());
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
None => {
|
Err(ref e) if e.kind() == ErrorKind::WouldBlock => {
|
||||||
self.machine_st.fail = true;
|
std::thread::sleep(std::time::Duration::from_millis(200));
|
||||||
}
|
if self.interrupt_occured() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
println!("IO error");
|
||||||
|
self.machine_st.fail = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user