snmalloc-rs: failing compilation with musl
Hi, I’m trying to build an application using snmalloc in with a statically linked musl libc instead of the gnu libc, during that we’ve been running in a few problems.
I am not sure 100% where the issue orriginates, from my research it seems to be related to the usage of C++
and global destructors.
The error boils down to:
/usr/local/bin/../lib/gcc/x86_64-linux-musl/9.2.0/../../../../x86_64-linux-musl/bin/ld: /target/x86_64-unknown-linux-musl/debug/deps/tremor-17be01d5a5f619ac: hidden symbol `__dso_handle' isn't defined
To make it easy I’ve created a minimal reproduction with nothing but snmalloc-rs and a mainline function:
https://github.com/Licenser/snmalloc-musl
The error can be triggered by simply running make
, it will build a musl docker image and then try to compile the application in it.
About this issue
- Original URL
- State: open
- Created 3 years ago
- Reactions: 4
- Comments: 24 (6 by maintainers)
The other option, of course, is for someone to contribute a
__cxa_thread_atexit_impl
to musl. It’s probably around a dozen lines of code and would fix this for everyone.@mjp41 😦 well, it was too early for me to have that belief… After several trials, I still cannot fix
MinGW
support even withpthread_key
. That is being said, I think the MUSL problem should be okay.__dso_handle
is a magic symbol that’s expected to be present with hidden visibility in every ELF shared library. It’s passed to the C++ runtime function that handles destructors so that, when a library is unloaded all of the destructors can be run (and all of the thread-local destructors can be skipped if the library has been unloaded). It’s usually provided by the CSU parts and might be missing with MUSL for statically linked binaries. I don’t know why MUSL doesn’t define it, because the C++ ABI requires that it exists, even for static linking.Last time I looked at the musl, it didn’t correctly handle library unloading even with shared libraries. It also doesn’t implement
__cxa_thread_atexit_impl
or__cxa_thread_atexit
at all, so the C++ runtime library has to fall back to usingpthread_setspecific
or similar for thread-local cleanup. I don’t know what the implication of that is for snmalloc: It doesn’t look as if musl needs to callfree
during thread teardown after it runs the thread-local destructors, so it’s probably fine.It is probably fine to just define something like this for static linking:
You might actually be able to get away with a weak symbol: it doesn’t matter if it resolves to 0, because the C++ runtime won’t do anything with it other than equality comparisons.
It would be nice if more libc implementations had the explicit ‘destroy malloc state for this thread’ hook that FreeBSD libc provides.
At’ing @mjp41 for visibility in case similar musl issues occur with other snmalloc bindings in other PLs
Yes but not with a super high priority. It prevents us to make statically linked tremor binaries, which is something we’d love to have, OTOH musl was significantly slower for us in the past when builds were working so they’d just be an addition not ‘the’ release strategy.
I think it’s totally fine to wait for a proper fix and not put a workaround on your plate 😃 we’re already super thankful that you all got to the bottom of this!
Would that fix MingW? But fixing musl would be good.
It looks as if Rust does this by using
pthread_setspecific
to register the TLS destructor. We could add an alternative implementation of ThreadAlloc that does this for musl and other pre-2011 C++ stacks. I’m slightly hesitant to do that because somepthread_setspecific
implementations callmalloc
but I wouldn’t have any objection to taking a patch to do it that’s sufficiently guarded behind#ifdef
s - it’s non-invasive.So I added
to the mainline, that resolves the compilation issue but causes it to segfault:
@davidchisnall any thoughts?