Skip to content

Commit

Permalink
Merge pull request #1598 from Pauan/fix-futures
Browse files Browse the repository at this point in the history
Fixing panic if the Future wakes up after returning Poll::Ready
  • Loading branch information
alexcrichton authored Jun 17, 2019
2 parents 379cad0 + 5a1dfdf commit b5da08c
Showing 1 changed file with 21 additions and 21 deletions.
42 changes: 21 additions & 21 deletions crates/futures/src/futures_0_3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,27 +233,27 @@ where

match lock.pop_front() {
Some(task) => {
let mut future = task.future.borrow_mut();

let poll = {
// This will only panic if the Future wakes up the Waker after returning Poll::Ready
let mut future = future.as_mut().unwrap_throw();

// Clear `is_queued` flag so that it will re-queue if poll calls waker.wake()
task.is_queued.set(false);

// This is necessary because the polled task might queue more tasks
drop(lock);

// TODO is there some way of saving these so they don't need to be recreated all the time ?
let waker = ArcWake::into_waker(task.clone());
let cx = &mut Context::from_waker(&waker);
Pin::new(&mut future).poll(cx)
};

if let Poll::Ready(_) = poll {
// Cleanup the Future immediately
*future = None;
let mut borrow = task.future.borrow_mut();

// This will only be None if the Future wakes up the Waker after returning Poll::Ready
if let Some(future) = borrow.as_mut() {
let poll = {
// Clear `is_queued` flag so that it will re-queue if poll calls waker.wake()
task.is_queued.set(false);

// This is necessary because the polled task might queue more tasks
drop(lock);

// TODO is there some way of saving these so they don't need to be recreated all the time ?
let waker = ArcWake::into_waker(task.clone());
let cx = &mut Context::from_waker(&waker);
Pin::new(future).poll(cx)
};

if let Poll::Ready(_) = poll {
// Cleanup the Future immediately
*borrow = None;
}
}
},
None => {
Expand Down

0 comments on commit b5da08c

Please sign in to comment.