From 8ec435d9b2c89b4e0f8025a8f849ba0b30c6e7c5 2022-04-22 13:22:43 From: MH Date: 2022-04-22 13:22:43 Subject: [PATCH] WIP on async control message bug regarding transferred closed ports --- diff --git a/src/runtime2/component/component_pdl.rs b/src/runtime2/component/component_pdl.rs index 8278f9b270dbf19094fabca7e6de128b79f9d9a0..f38875e2ea0a113a9f4d5dcda5cc35f60ca5ae43 100644 --- a/src/runtime2/component/component_pdl.rs +++ b/src/runtime2/component/component_pdl.rs @@ -763,16 +763,28 @@ impl CompPDL { } } - // Do the same for the closed ports + // Do the same for the closed ports. Note that we might still have to + // transfer messages that cause the new owner of the port to fail. for pair in closed_port_id_pairs.iter() { let port_index = creator_ctx.get_port_index(pair.creator_handle); creator_ctx.remove_port(pair.creator_handle); - let _removed_message = self.inbox_main.remove(port_index); + if let Some(mut message) = self.inbox_main.remove(port_index) { + message.data_header.target_port = pair.created_id; + component.component.adopt_message(&mut component.ctx, message); + } - // In debug mode: since we've closed the port we shouldn't have any - // messages for that port. - debug_assert!(_removed_message.is_none()); - debug_assert!(!self.inbox_backup.iter().any(|v| v.data_header.target_port == pair.creator_id)); + let mut message_index = 0; + while message_index < self.inbox_backup.len() { + let message = &self.inbox_backup[message_index]; + if message.data_header.target_port == pair.created_id { + // Transfer message + let mut message = self.inbox_backup.remove(message_index); + message.data_header.target_port = pair.created_id; + component.component.adopt_message(&mut component.ctx, message); + } else { + message_index += 1; + } + } } // By now all ports and messages have been transferred. If there are any diff --git a/src/runtime2/tests/error_handling.rs b/src/runtime2/tests/error_handling.rs index 8405520d7e74f57b8ac02a1828d3bc86ae275d95..ddf0d1dbbd6fdef77a1cc4b6156596b399d76f1d 100644 --- a/src/runtime2/tests/error_handling.rs +++ b/src/runtime2/tests/error_handling.rs @@ -2,19 +2,16 @@ use super::*; #[test] fn test_unconnected_component_error() { - let pd = ProtocolDescription::parse(b" + compile_and_create_component(" primitive interact_with_noone() { u8[] array = { 5 }; auto value = array[1]; - } - ").unwrap(); - let rt = Runtime::new(1, true, pd).unwrap(); - create_component(&rt, "", "interact_with_noone", no_args()); + }", "interact_with_noone", no_args()); } #[test] fn test_connected_uncommunicating_component_error() { - let pd = ProtocolDescription::parse(b" + compile_and_create_component(" primitive crashing_and_burning(out unused) { u8[] array = { 1337 }; auto value = array[1337]; @@ -26,7 +23,26 @@ fn test_connected_uncommunicating_component_error() { channel a -> b; new sitting_idly_waiting(b); new crashing_and_burning(a); - }").unwrap(); - let rt = Runtime::new(1, true, pd).unwrap(); - create_component(&rt, "", "constructor", no_args()); + }", "constructor", no_args()) +} + +#[test] +fn test_connected_communicating_component_error() { + compile_and_create_component(" + primitive send_and_fail(out tx) { + u8[] array = {}; + sync { + put(tx, 0); + array[0] = 5; + } + } + primitive receive_once(in rx) { + sync auto a = get(rx); + } + composite constructor() { + channel a -> b; + new send_and_fail(a); + new receive_once(b); + } + ", "constructor", no_args()) } \ No newline at end of file diff --git a/src/runtime2/tests/mod.rs b/src/runtime2/tests/mod.rs index 6583f36c165d9eb7156bf872c743371240a15fc8..b139ad3ad26b8119bccdbfb57b8b0377e01e9578 100644 --- a/src/runtime2/tests/mod.rs +++ b/src/runtime2/tests/mod.rs @@ -5,6 +5,17 @@ use crate::runtime2::component::{CompCtx, CompPDL}; mod error_handling; +const NUM_THREADS: u32 = 1; +const DEBUG_LOGGING: bool = true; + +pub(crate) fn compile_and_create_component(source: &str, routine_name: &str, args: ValueGroup) { + let protocol = ProtocolDescription::parse(source.as_bytes()) + .expect("successful compilation"); + let runtime = Runtime::new(NUM_THREADS, DEBUG_LOGGING, protocol) + .expect("successful runtime startup"); + create_component(&runtime, "", routine_name, args); +} + pub(crate) fn create_component(rt: &Runtime, module_name: &str, routine_name: &str, args: ValueGroup) { let prompt = rt.inner.protocol.new_component( module_name.as_bytes(), routine_name.as_bytes(), args