Open Dirbaio opened 8 months ago
As of 9ff2b37f559a99f84c484edc6c9d258b43119fa6, Miri no longer complains.
the other issues still stand though!
it's fundamentally unsound to allocate tasks in the stack and make wakers point directly to the tasks.
@Dirbaio I think I have a solution, currently sitting in pinned_tasks. Both futures_util::pin_mut!
and core::pin::pin!
take ownership of the task, ensuring that they cannot be core::mem::forget
ed.
That doesn't fix the 1st issue "Wakers contain a pointer to stack-allocated tasks, and nothing prevents the task from being deallocated while there still are wakers pointing to it.".
Wakers are 'static
. Once you get a waker pointing to a task, you can store it literally anywhere, forever. If the task is pinned then you're guaranteed its Drop will run, but there's no way to make Drop "recall" all the wakers pointing to the task that could be stored anywhere across the whole program.
It's possible to do if you add indirection to the wakers. Like, store a "task ID" in wakers, executor contains an id->pointer map so you can mark the id as "stale" on task drop to "deactivate" all the wakers. This adds complexity and hurts perf tho.
I've looked at this hard over the years and my conclusion is the only two good designs are either to alloc+refcount tasks (what most std executors do) or statically allocate tasks so they live forever (what embassy-executor and RTIC do). There's no way to stack-allocate tasks with good perf.
Yes, Wakers are the unsolvable issue.
I'd originally written this crate way back in 2020 when as far as I could see there wasn't really a way of doing async on bare metal. Since then both embassy
and RTIC
have flourished, and if fact I use embassy
for my personal projects. As such, I think it's time to deprecate and retire nostd_async
.
Do you by any chance know how I might do this?
Possibilities include:
nostd_async
mem::forget
theJoinHandle
(preventing the task from getting unlinked byJoinHandle
drop) which releases the borrow on the task, and then move the task, which will break the linked list pointers.cargo miri test
andcargo miri run --example ...
fail. I haven't looked deep in the code to know whether this is due to the above issues, or to other issues.