Skip to content

Commit d18e5df

Browse files
authored
io: fix race in Mock::poll_write (#7882)
1 parent f21f269 commit d18e5df

1 file changed

Lines changed: 24 additions & 1 deletion

File tree

tokio-test/src/io.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,30 @@ impl AsyncWrite for Mock {
438438
let until = Instant::now() + rem;
439439
self.inner.sleep = Some(Box::pin(time::sleep_until(until)));
440440
} else {
441-
panic!("unexpected WouldBlock {}", self.pmsg());
441+
// A race condition (TOCTOU) can occur if the
442+
// timer expires between the `write()` call
443+
// and `remaining_wait()` due to preemption or other
444+
// delays. In this case, the `Wait` action is already popped by
445+
// `action()`, so we continue to the next one.
446+
//
447+
// Consider the following sequence:
448+
//
449+
// poll_write Inner action()
450+
// |--write()--->| |
451+
// | |--action()---->| (returns Wait)
452+
// |<-WouldBlk---| |
453+
// | | |
454+
// | <--- TIMEOUT! ---> |
455+
// | (due to preemption, etc.) |
456+
// | | |
457+
// |-rem_wait()->| |
458+
// | |--action()---->| (time's up, pop Wait)
459+
// |<--None------| |
460+
// | | |
461+
// |---continue->| (process next action)
462+
//
463+
// See <https://github.com/tokio-rs/tokio/issues/7881>.
464+
continue;
442465
}
443466
}
444467
Ok(0) => {

0 commit comments

Comments
 (0)