bevyengine / bevy

A refreshingly simple data-driven game engine built in Rust
https://bevyengine.org
Apache License 2.0
33.99k stars 3.31k forks source link

Window hangs, refuses to close with a `NonSend`/`NonSendMut` system parameter in the `render_app` #12912

Open simbleau opened 3 months ago

simbleau commented 3 months ago

Bevy version

v0.13.2

[Optional] Relevant system information

This took forever to find, but simply having a system that has a fn ...(x: NonSend(_)) {}

added to the render app with default plugins will cause an infinite hang when you try to close the window. Not sure why.

We encountered this in the bevy_vello demo, if ran on native platforms.

The line specifically is: https://github.com/loopystudios/bevy_vello/blob/dcf1584ead46ad19ff72d7f34110e00f415263f9/src/render/systems.rs#L60

This has been tested and verified on both MacOS and Windows.

It applies to both NonSend and NonSendMut

seabassjh commented 3 months ago

I can reproduce this

james7132 commented 3 months ago

This makes sense since NonSend resources must be dropped on the thread in which they're initialized. With pipelined rendering enabled, the render app/world are sent to a dedicated thread, and ping-pongs between the main thread and the render thread. If you initialized the NonSend resource on the main thread, it shouldn't be accessible on any other thread.

If you can avoid using a !Send type as a resource, I strongly suggest avoiding it if possible. If that isn't possible, you may want add it to the main app and use a Send proxy that is used in the render app. This is what bevy_winit does.

Long term, we are planning on moving !Send resources from the World entirely, moving them into App instead. See #9122.

alice-i-cecile commented 3 months ago

To add to that, subapps are likely to be replaced with a world-based abstraction, rather than a full app, eliminating this footgun completely.

simbleau commented 3 months ago

This makes sense since NonSend resources must be dropped on the thread in which they're initialized. With pipelined rendering enabled, the render app/world are sent to a dedicated thread, and ping-pongs between the main thread and the render thread. If you initialized the NonSend resource on the main thread, it shouldn't be accessible on any other thread.

If you can avoid using a !Send type as a resource, I strongly suggest avoiding it if possible. If that isn't possible, you may want add it to the main app and use a Send proxy that is used in the render app. This is what bevy_winit does.

Long term, we are planning on moving !Send resources from the World entirely, moving them into App instead. See #9122.

To add to that, subapps are likely to be replaced with a world-based abstraction, rather than a full app, eliminating this footgun completely.

Depending on how long the above solutions will take, this should be documented in NonSend/NonSendMut. There's no mention of this footgun. ;)

alice-i-cecile commented 3 months ago

Yep, totally happy to see a note added to the documentation.