ITADN

Potential double free issue

#856Closedabh1nav10 创建于 2026-04-10
A
abh1nav10commented
`Task::run` has got the invariant that it must not be called if the state for the task is `COMPLETED`. However, that might get violated assuming this scenario- Assume we have a future that when polled clones the waker and stores it in some shared state that can be accessed by another thread like- ```rust use std::pin::Pin; use std::sync::{Arc, Mutex}; use std::task::{Context, Poll, Waker}; struct CounterFuture { count: usize, waker: Arc<Mutex<Option<Waker>>>, } impl Future for CounterFuture { type Output = (); fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { self.count += 1; if self.count >= 2 { Poll::Ready(()) } else { let waker = cx.waker().clone(); *self.waker.lock().unwrap() = Some(waker); Poll::Pending } } } ``` The executor calls `Task::poll` which calls `TaskAlloc::run_future`. The future returns `Poll::Pending` on the first poll. If we wake the Waker using the shared state the future runs again, however, before the `poll` function could call `finish_running` on the state, the kernel preempts it. Now, if the other thread wakes up the `Waker` through the shared state again, we call `Task::schedule` which would then call `Remote::schedule` whose initial check to see is the state is `COMPLETED` will fail because the executor was prempted earlier on. It will proceed to push the task in the `sync-queue`. The executor will end up polling it again and since it does not check whether the state was `COMPLETED` before calling `TaskAlloc::run_future` it will lead to `run_future` seeing `Poll::Ready` immediately in which case it drops the future again. I think the fix would be to add an `is_completed` check in `Task::run` along with the `is_cancelled` check that is already there. Please correct me if i am missing something but happy to make a PR is it is a genuine fix.
关闭于 2026-04-10 8 条评论