Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unloading/reloading dynamic plugins #4843

Closed
rishflab opened this issue May 26, 2022 · 7 comments · Fixed by #13080
Closed

Unloading/reloading dynamic plugins #4843

rishflab opened this issue May 26, 2022 · 7 comments · Fixed by #13080
Labels
A-App Bevy apps and plugins C-Feature A new feature, making something new possible

Comments

@rishflab
Copy link

rishflab commented May 26, 2022

What problem does this solve or what need does it fill?

Currently bevy supports the loading of plugins at runtime. By adding support for unloading/reloading will allow gamedevs to make changes to a module and test it without restarting the game process and resetting state. Shortening the feedback loop to test gameplay changes makes dev faster.

What solution would you like?

Add unload and reload methods to App via DynamicExt trait. I am happy to explore and flesh this out further but would like to get some feedback on the idea first. Is this even possible? How much work would it be?

What alternative(s) have you considered?

None

Additional context

None

@rishflab rishflab added C-Feature A new feature, making something new possible S-Needs-Triage This issue needs to be labelled labels May 26, 2022
@alice-i-cecile alice-i-cecile added A-App Bevy apps and plugins and removed S-Needs-Triage This issue needs to be labelled labels May 26, 2022
@bjorn3
Copy link
Contributor

bjorn3 commented May 26, 2022

Musl doesn't support dlclose at all and makes it a nop. Other libc's (for example macOS's libc) only allow it when TLS is not used and silently ignore dlclose otherwise. In any case it is pretty much impossible to do it safely as bevy can't enumerate al possible places a pointer into the plugin dylib is left over to santize.

@rishflab
Copy link
Author

rishflab commented May 28, 2022

I don't know much about dynamic loading at the OS level so sorry if the following comments/questions are stupid.

Musl doesn't support dlclose at all and makes it a nop. Other libc's (for example macOS's libc) only allow it when TLS is not used and silently ignore dlclose otherwise.

Isn't the dynamic lib loaded into memory of the game process. To "close" or unload it we can simply drop all the libloading::Library and libloading::Symbol instances?

In any case it is pretty much impossible to do it safely as bevy can't enumerate al possible places a pointer into the plugin dylib is left over to santize.

Correct me if I am wrong, it seems like the issue is that the way that bevy is designed, pointers to the dynamic lib ie libloading::Symbol are spread everywhere and therefore difficult to drop when trying to unload or reload a library. Hot reloading is possible to do but would require a lot of changes to bevy?

@bjorn3
Copy link
Contributor

bjorn3 commented May 28, 2022

To "close" or unload it we can simply drop all the libloading::Library and libloading::Symbol instances?

No, dropping libloading::Library uses dlclose, which can't be depended upon as I said.

Hot reloading is possible to do but would require a lot of changes to bevy?

Not, just bevy, but to rust the language too. The changes to rust would cause wide spread breakage. Even something as simple as starting a thread or registering a tracing logger layer will keep pointers to the dylib. Unity can handle unloading because it is programmed in C# which uses a GC. To make a GC work, the .net runtime knows about every pointer in the whole program. Furthermore Unity uses a feature of .net to create compartments. And finally I think the .net runtime will keep dylibs in memory if there are still pointers to it pending, while still allowing further method calls to be replaced. The closest thing we can do would be to use wasm rather than native dylibs.

tl;dr: The equivalent of dlclose can only be made safe in managed languages. Rust is not a managed language. Wasm is a possiblity for reloading dynamic plugins.

@rishflab
Copy link
Author

rishflab commented May 29, 2022

To "close" or unload it we can simply drop all the libloading::Library and libloading::Symbol instances?

No, dropping libloading::Library uses dlclose, which can't be depended upon as I said.

Hot reloading is possible to do but would require a lot of changes to bevy?

Not, just bevy, but to rust the language too. The changes to rust would cause wide spread breakage. Even something as simple as starting a thread or registering a tracing logger layer will keep pointers to the dylib. Unity can handle unloading because it is programmed in C# which uses a GC. To make a GC work, the .net runtime knows about every pointer in the whole program. Furthermore Unity uses a feature of .net to create compartments. And finally I think the .net runtime will keep dylibs in memory if there are still pointers to it pending, while still allowing further method calls to be replaced. The closest thing we can do would be to use wasm rather than native dylibs.

tl;dr: The equivalent of dlclose can only be made safe in managed languages. Rust is not a managed language. Wasm is a possiblity for reloading dynamic plugins.

ah thats a bummer but thanks for that explanation, really helpful : )

@BD103
Copy link
Member

BD103 commented May 20, 2024

This current implementation of dynamic plugins are being deprecated and will be removed in Bevy 0.15, which is why this is being closed.

I do think this is a useful feature that should be considered if we ever create a new system, though.

@aschrijver
Copy link

aschrijver commented Jun 6, 2024

Would webassembly be able to offer such a new system (previously discussed in thoughts on WebAssembly modding? Extism is an example of a universal plugin framework, yet I dunno if it'd support the needs of Bevy.

@BD103
Copy link
Member

BD103 commented Jun 6, 2024

Would webassembly be able to offer such a new system

Perhaps, though for now I think it's best as a 3rd party plugin.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-App Bevy apps and plugins C-Feature A new feature, making something new possible
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants