From 5a1dfdf2abab8b8ff7aca34bd9698125acbe86c7 Mon Sep 17 00:00:00 2001 From: Pauan Date: Sat, 15 Jun 2019 15:08:34 +0200 Subject: [PATCH] Fixing panic if the Future wakes up after returning Poll::Ready --- crates/futures/src/futures_0_3.rs | 42 +++++++++++++++---------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/crates/futures/src/futures_0_3.rs b/crates/futures/src/futures_0_3.rs index 24f71b34dfa..76df7204395 100644 --- a/crates/futures/src/futures_0_3.rs +++ b/crates/futures/src/futures_0_3.rs @@ -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 => {