Skip to content

Commit ced7992

Browse files
authoredJul 22, 2021
runtime: add large test and fix leak it found (#3967)
1 parent 0cefa85 commit ced7992

File tree

4 files changed

+430
-39
lines changed

4 files changed

+430
-39
lines changed
 

‎tokio/src/runtime/task/harness.rs

+31-12
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,8 @@ where
111111
}
112112

113113
pub(super) fn drop_join_handle_slow(self) {
114+
let mut maybe_panic = None;
115+
114116
// Try to unset `JOIN_INTEREST`. This must be done as a first step in
115117
// case the task concurrently completed.
116118
if self.header().state.unset_join_interested().is_err() {
@@ -119,11 +121,20 @@ where
119121
// the scheduler or `JoinHandle`. i.e. if the output remains in the
120122
// task structure until the task is deallocated, it may be dropped
121123
// by a Waker on any arbitrary thread.
122-
self.core().stage.drop_future_or_output();
124+
let panic = panic::catch_unwind(panic::AssertUnwindSafe(|| {
125+
self.core().stage.drop_future_or_output();
126+
}));
127+
if let Err(panic) = panic {
128+
maybe_panic = Some(panic);
129+
}
123130
}
124131

125132
// Drop the `JoinHandle` reference, possibly deallocating the task
126133
self.drop_reference();
134+
135+
if let Some(panic) = maybe_panic {
136+
panic::resume_unwind(panic);
137+
}
127138
}
128139

129140
// ===== waker behavior =====
@@ -182,17 +193,25 @@ where
182193
// ====== internal ======
183194

184195
fn complete(self, output: super::Result<T::Output>, is_join_interested: bool) {
185-
if is_join_interested {
186-
// Store the output. The future has already been dropped
187-
//
188-
// Safety: Mutual exclusion is obtained by having transitioned the task
189-
// state -> Running
190-
let stage = &self.core().stage;
191-
stage.store_output(output);
192-
193-
// Transition to `Complete`, notifying the `JoinHandle` if necessary.
194-
transition_to_complete(self.header(), stage, &self.trailer());
195-
}
196+
// We catch panics here because dropping the output may panic.
197+
//
198+
// Dropping the output can also happen in the first branch inside
199+
// transition_to_complete.
200+
let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| {
201+
if is_join_interested {
202+
// Store the output. The future has already been dropped
203+
//
204+
// Safety: Mutual exclusion is obtained by having transitioned the task
205+
// state -> Running
206+
let stage = &self.core().stage;
207+
stage.store_output(output);
208+
209+
// Transition to `Complete`, notifying the `JoinHandle` if necessary.
210+
transition_to_complete(self.header(), stage, &self.trailer());
211+
} else {
212+
drop(output);
213+
}
214+
}));
196215

197216
// The task has completed execution and will no longer be scheduled.
198217
//

‎tokio/src/runtime/tests/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ cfg_loom! {
4040
cfg_not_loom! {
4141
mod queue;
4242

43+
#[cfg(not(miri))]
44+
mod task_combinations;
45+
4346
#[cfg(miri)]
4447
mod task;
4548
}

0 commit comments

Comments
 (0)