__cxa_get_globals() problem on mingw

If I create a dll that throws and catches exceptions internally, then load it into an application and unload it, the application will crash as soon as a thread exits.

The crash is because __cxa_get_globals() allocates a tls-key that is not freed when the dll is unloaded, so the callback that was set (with FlsAlloc() via __libcpp_tls_create()) now points into non-existing code.

This will happen if the dll is statically linked against libc++ or if the main application does not use libc++. If both the main app and the dll are dynamically linked I guess it will not happen.

As a workaround I made a function __libcpp_tls_destroy() that is registered with atexit() when the tls-key is created in libcxxabi/src/cxa_exception_storage.cpp.

I was going to propose a patch, but I don’t know if it is ok to use atexit() like this, and there are probably ABI-concerns.

I think there may be a similar problem with the tls-key in __thread_specific_ptr, but since this destructor is inlined I guess there could be an ABI break to add a dependency on a cleanup function there?

/Kalle

@mstorsjo might be best suited to help out here

Hi @kalle, and sorry for the long delay in responding.

I set up an example according to your description, and I can indeed reproduce such a problem. Your explanation sounds reasonable to me. I can’t say for sure about your suggested fix, I think it might be ok; the best would certainly be to upload it for review so we can discuss it better in context there, and if agreed upon, merge the fix.

Thanks for your report and contribution!

Great, thank you.

I’ve made a tentative patch at ⚙ D155278 [libc++][mingw] TLS cleanup on windows.