Skip to content

Commit

Permalink
handle node killed
Browse files Browse the repository at this point in the history
Signed-off-by: Bugen Zhao <[email protected]>
  • Loading branch information
BugenZhao committed Oct 10, 2024
1 parent 5cab519 commit 5dab5d3
Showing 1 changed file with 40 additions and 5 deletions.
45 changes: 40 additions & 5 deletions madsim/src/sim/task/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -630,7 +630,7 @@ impl Spawner {
F::Output: 'static,
{
if self.info.killed.load(Ordering::Relaxed) {
panic!("spawning task on a killed node");
tracing::warn!("spawning task on a killed node, the task will never run");
}
let sender = self.sender.clone();
let info = self.info.new_task(name);
Expand Down Expand Up @@ -795,8 +795,8 @@ unsafe extern "C" fn pthread_attr_init(attr: *mut libc::pthread_attr_t) -> libc:
mod tests {
use super::*;
use crate::{
context::current_node,
runtime::{Handle, Runtime},
context::{current, current_node},
runtime::{init_logger, Handle, Runtime},
time,
};
use std::{collections::HashSet, sync::atomic::AtomicUsize, time::Duration};
Expand Down Expand Up @@ -1109,8 +1109,7 @@ mod tests {
}

#[test]
#[allow(dead_code)]
fn spawn_in_task_drop() {
fn spawn_in_future_drop_by_aborting_task() {
static DROPPING_NODE: Mutex<Option<NodeId>> = Mutex::new(None);

struct A;
Expand Down Expand Up @@ -1143,4 +1142,40 @@ mod tests {
assert_eq!(DROPPING_NODE.try_lock().unwrap().unwrap(), node_id);
})
}

#[test]
fn spawn_in_future_drop_by_killing_node() {
init_logger();

static DROPPED: Mutex<bool> = Mutex::new(false);

struct A;

impl Drop for A {
fn drop(&mut self) {
// Spawning a task on a killed node will still succeed, but the task will never run.
spawn(async move { unreachable!() });
*DROPPED.try_lock().unwrap() = true;
}
}

let runtime = Runtime::new();
let node = runtime.create_node().build();
let node_id = node.id();
let a = A;

runtime.block_on(async move {
// Since we're a single-threaded runtime, task spawning here won't run proactively.
// So `drop` will only be called after we call `kill` and while `await`ing the handle.
let join_handle = node.spawn(async move { drop(a) });
current(|handle| handle.kill(node_id));

let err = join_handle.await.unwrap_err();
assert!(err.is_cancelled());
assert_eq!(*DROPPED.try_lock().unwrap(), true);

// Give some time, showing that the task spawned in `A::drop` is never run.
time::sleep(Duration::from_secs(114514)).await;
})
}
}

0 comments on commit 5dab5d3

Please sign in to comment.