-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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 a Rust dylib with TLS used segfaults on OSX #28794
Comments
|
cc @emoon |
Has there been any progress on this issue? It can be worked around but not releasing the lib but it would be nice to have a proper solution. |
ProDBG crashes on exit but that is due to rust-lang/rust#28794 Closes #177
I had the same issue, one workaround was loading the lib with RTLD_NODELETE. |
I think I'm having the same issue? But the RTLD_NODELETE option doesn't seem to help. It's also probably not appropriate for my use-case, which requires unloading and reloading the library repeatedly. Stack looks like this: Exception Type: EXC_BAD_ACCESS (SIGSEGV) Thread 0 Crashed:: Dispatch queue: com.apple.main-thread |
Lack of |
Hmm, I got the impression from that comment that it would be fixed by default... I'll look into it, thanks. |
Copying code into here so it doesn't get lost; nagisa/rust_libloading#5 is potentially relevant. test.rs: #[no_mangle]
pub extern "system" fn test_fn() -> i32 {
// Removing this line prevents the segfault.
// I've tried flushing stdout as well but it doesn't change anything
println!("In library!");
123456
} main.c: #include <dlfcn.h>
#include <stdio.h>
int main() {
printf("running\n");
void* handle = dlopen("./libtest.dylib", RTLD_LAZY);
printf("opened: %p\n", handle);
int (*test_fn)() = dlsym(handle, "test_fn");
printf("test_fn: %d\n", test_fn());
printf("Closing...\n");
int code = dlclose(handle); // Removing this line prevents the segfault upon exit?
printf("Closed: %d.\n", code);
}
|
Mention of |
I ran into this and looked at ways to work around this. It comes up with Python extension modules and so far we just decided to leak the module. The reason this cannot really be fixed to the best of my knowledge is that Since the only callback that rust can reasonably place here is from the dylib we can't really register something here that does not crash if the dylib goes away. One would need to find a trampoline that can be used and does not unload. Unsure what the fix here is. This seems like a bug in macos albeit one that has low changes of fixing. |
I'm getting something similar on Arch: https://github.com/BurntPizza/dylib_tls_crash
The difference here is that the segfault happens when a (non-main) thread exits, if there has been a dylib dropped in that thread, even if the lib doesn't contain anything (source-wise). Various things can be found be searching for __nptl_deallocate_tsd but this seems above my pay grade. The most promising thing was this comment and the patch after it: https://bugzilla.redhat.com/show_bug.cgi?id=1065695#c12 Info:
Should I make a separate issue? |
This seems to have been fixed by some On the other hands, this means that Rust dylibs will never be unloaded on OS X? |
Are we 100% sure the issue is with TLS? I've got TLS working without segfault through a dlclose (and reopen) on macOS Sierra (10.12.6), but only if the dylib statically links to libstd. If the dylib is dynamically linked to libstd, then I get a segfault on dlclose regardless of whether or not I'm using TLS. This is on stable rustc 1.24.0. This is good enough for my use case (code hot reloading during development), but it would be nice to remove the requirement to statically link libstd into the dylib. |
@scottjmaddox this particular crash is from what's registered to |
WWDC 2017's Session 413 @ 29:36 mentions that using TLS prevents a dylib from being unloaded:
|
@alexcrichton seems like MacOS people have fixed this. Should we close? |
Sure! |
The bug was fixed, no need for the note now: rust-lang/rust#28794
Example code
The problem here is that we register a TLS destructor via
_tlv_atexit
when TLS is referenced the first time after it is used (e.g. when the dylib's function is called), but then whendlclose
happens the function isn't actually there and a fault happens when the thread exits and tries to run its destructors.I'm not entirely sure how we might handle this, perhaps there's a way to compile dylibs such that the TLS access is OK? Perhaps we should hook an "unload" event and deregister (e.g. leak) TLS destructors? Either way seems like a good thing to track!
The text was updated successfully, but these errors were encountered: