crux
crux copied to clipboard
Fix a bug caused by drop order of the `Core` struct
This is a very subtle problem with the order of the fields of the Core
type interacting with the async runtime when using channels (and possibly other coordination primitives).
The problem is this:
- A capability creates a long running future with a loop
- In order to communicate with this future it creates a channel, gives the receving end to the future and holds the sending end
- The future gets to the point of receiving from the channel and suspends on
.await
. - If the core is now dropped, then due to the original ordering of the fields, the executor is dropped first, causing the
task_sender
channel to close. - The
A::Capabilities
instance is dropped, dropping the capability instance, including the sending end of the channel - The channel's
Drop
implementation closes the channel, which wakes up the future, so that therecv()
method can returnErr
- The
ArcWake
implementation on the task spawned by Crux'sSpawner
attempts to.send
self to thetask_sender
, which fails, because the receving end dropped in step 4, and we panic on the.expect
To fix, I've reordered the fields of Core to drop the user defined types first, so that any Crux infrastructure they rely on is still alive when any Drop
implementations in them run.