-
Notifications
You must be signed in to change notification settings - Fork 77
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
Extension dylibs aren't being unloaded on Hot Reload #384
Comments
In fact the extension can be as simple as @_cdecl("swift_entry_point") public func enterExtension (interface: OpaquePointer?, library: OpaquePointer?, extension: OpaquePointer?) -> UInt8 {
return 1
}
class SomeClass {} with no dependencies at all and the issue will still be reproducible. It just needs a little tweak in Godot's source code (godotengine/godot#87938), since Godot does not properly handle null in Looking into Godot's extension reload, The function dlclose() decrements the reference count on the dynamic library handle handle. If the reference count drops to zero and no other loaded libraries use symbols in it, then the dynamic library is unloaded. |
I do not think this is a Godot issue, but an interoperability issue between Swift and loading dynamic modules. I created a very simple sample (https://tirania.org/tmp/demo-swift-dlopen.tar.gz) that exhibits the same issue, here is the sample for the main program:
And then I replace |
And I can no longer reproduce the error. I am not sure what I did, but now I am able to load both libraries, and the warning is gone, and the libraries do show the right output. |
I am unable to hot reload the swift library in my project as well . i am getting these editor errors , when updating the library and building it using ERROR: Attempt to register extension class 'PlayerController', which appears to be already registered.
at: _register_extension_class_internal (core/extension/gdextension.cpp:463)
ERROR: Attempt to register extension class 'PxPlayer', which appears to be already registered.
at: _register_extension_class_internal (core/extension/gdextension.cpp:463) this is my
|
There is a new fix for this specific issue on main, can you try it? |
I did my testing on |
#449 probably related |
Ok, I spent some quality time on this issue, and there are two sets of problems: (a) The current de-init code is slightly buggy, and it only de-initializes some parts, but not all. So even if you produce a new binary, What is puzzling is that a standalone C program loading Swift code and unloading it works, but something that Godot is doing prevents these extensions from being reloaded, because the same sample that can be unloaded and reloaded by the C program (with no SwiftGodot dependencies) fails to be reloaded when used inside Godot. The sample extension I am using with Swift is this, notice that there are not dependencies on SwiftGodot at all:
And this extension with this sample C program can be modified, and it will successfully reload it:
|
It sounds like you're saying the simple sample here won't be reloaded correctly if used as a GDExtension with Godot? I attempted to reproduce this on Linux, and it seemed to work fine for me, although, this is my first time using Swift, so I may be missing something. :-) I used your sample program above: var value = 1
@_cdecl("extension_init")
public func enterExtension () {
print ("This is the library \(value)")
} Which I compiled with:
With this
To test, I changed I'll try the same process on MacOS in a little bit... |
Interestingly, I am able to reproduce the problem on MacOS, following the same process as above! The output in the terminal won't change until I restart the Godot editor. So, it seems to be specific to MacOS in some way. I also tried making a similar sample extension in C with this code: #include <stdio.h>
int c_extension_init(void *p1, void *p2, void *p3) {
int value = 1;
printf("C Lib %d\n", value);
return 0;
} Compiled with:
And, the C version didn't have this issue! I could change So, the issue is somehow specific to MacOS and Swift, and (per @migueldeicaza's earlier testing) it only happens when the extension is loaded by Godot. This is very interesting problem... |
I did some testing on both platforms, Hot reloading works fine on windows but it does not when using the SwiftGodot on MacOs |
Swift is associated with Objective-C on the Apple platform, and the library loader (dyld) prevents uninstalling dynamic libraries with objc sections. Therefore, dlclose is usually not functional on the Apple platform. |
But in this case, we have a library that can be unloaded without Godot, but not with Godot. Perhaps it is Godot's use of Objective-C that triggers this behavior? But if so, why would Rust still work. |
This post from Apple Developer Support may give a little more context: https://forums.developer.apple.com/forums/thread/122591 In particular, Quinn's final reply:
I don't think that this is ever likely to work, sadly. |
I am less concern about unloading the dynamic library than being able to load a new instance of it. If the code remains in memory and unused, it can be swapped out, what I believe should be done is that Godot should copy the library to a unique name on MacOS, and then load the new library, that will still keep the old around (but it is not in use) and load the new one. |
Wouldn't you still get symbol collisions? I'm not sure that the dynamic linker would be smart enough to prefer the latest loaded version. Something like the approach here and/or here might work though. |
I don't think so. You use dlsym manually against a specific handle. |
An interesting update: godotengine/godot#90108 (comment) I will try the samples here later, but did not want to miss this information. |
Folks, an even more interesting update. This comment from @jordo in the issue:
The gdext-nim issue also lists two bits of Rust code that were added to support it. This being an issue for Linux: |
This was originally mentioned in #273
I made a simplistic entry point using
GDExtension
target as the only dependency:And configured gdextension as reloadable:
This was enough to reproduce the issue:
This will result in
The text was updated successfully, but these errors were encountered: