Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test combinations of task behavior #3967

Merged
merged 16 commits into from Jul 22, 2021
43 changes: 31 additions & 12 deletions tokio/src/runtime/task/harness.rs
Expand Up @@ -112,6 +112,8 @@ where
}

pub(super) fn drop_join_handle_slow(self) {
let mut maybe_panic = None;

// Try to unset `JOIN_INTEREST`. This must be done as a first step in
// case the task concurrently completed.
if self.header().state.unset_join_interested().is_err() {
Expand All @@ -120,11 +122,20 @@ where
// the scheduler or `JoinHandle`. i.e. if the output remains in the
// task structure until the task is deallocated, it may be dropped
// by a Waker on any arbitrary thread.
self.core().stage.drop_future_or_output();
let panic = panic::catch_unwind(panic::AssertUnwindSafe(|| {
self.core().stage.drop_future_or_output();
}));
if let Err(panic) = panic {
maybe_panic = Some(panic);
}
}

// Drop the `JoinHandle` reference, possibly deallocating the task
self.drop_reference();

if let Some(panic) = maybe_panic {
panic::resume_unwind(panic);
}
}

// ===== waker behavior =====
Expand Down Expand Up @@ -183,17 +194,25 @@ where
// ====== internal ======

fn complete(self, output: super::Result<T::Output>, is_join_interested: bool) {
if is_join_interested {
// Store the output. The future has already been dropped
//
// Safety: Mutual exclusion is obtained by having transitioned the task
// state -> Running
let stage = &self.core().stage;
stage.store_output(output);

// Transition to `Complete`, notifying the `JoinHandle` if necessary.
transition_to_complete(self.header(), stage, &self.trailer());
}
// We catch panics here because dropping the output may panic.
//
// Dropping the output can also happen in the first branch inside
// transition_to_complete.
let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| {
if is_join_interested {
// Store the output. The future has already been dropped
//
// Safety: Mutual exclusion is obtained by having transitioned the task
// state -> Running
let stage = &self.core().stage;
stage.store_output(output);

// Transition to `Complete`, notifying the `JoinHandle` if necessary.
transition_to_complete(self.header(), stage, &self.trailer());
} else {
drop(output);
}
}));

// The task has completed execution and will no longer be scheduled.
//
Expand Down
3 changes: 3 additions & 0 deletions tokio/src/runtime/tests/mod.rs
Expand Up @@ -40,6 +40,9 @@ cfg_loom! {
cfg_not_loom! {
mod queue;

#[cfg(not(miri))]
mod task_combinations;

#[cfg(miri)]
mod task;
}