Skip to content

Commit 3845586

Browse files
committed
Commit & document workaround for TLV/TLS & exit terminator issues.
Avoids crashes on exit for multiple libraries on multiple OS. Will hopefully document with specifics in future. Note: This means libraries cannot be unloaded/reloaded/closed before program exit.
1 parent 7c26301 commit 3845586

File tree

1 file changed

+35
-1
lines changed

1 file changed

+35
-1
lines changed

src/crossplatform.cpp

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,39 @@ std::string error_number_as_string;
77

88
HANDLE open_library(const char *path) {
99
#ifdef IS_UNIX
10-
return dlopen(path, RTLD_LAZY); // TODO: Is RTLD_LAZY the best?
10+
//
11+
// Note: Experience has shown that multiple platforms/libraries
12+
// have issues with handling dynamically loaded shared
13+
// libraries and Thread Local Variables/Thread Local Storage
14+
// and/or at exit terminators properly.
15+
//
16+
// This can result in multiple thread crashes when the
17+
// program exits because the library is no longer loaded
18+
// but pointers to the library clean-up functions still exist.
19+
//
20+
// The best workaround found so far is to...just not unload
21+
// a library when it is closed. :/
22+
//
23+
// The workaround is implemented via the addition of an
24+
// additional `dlopen()` call which is (by design) never
25+
// matched with a `dlclose()` call. This results in all
26+
// at exit/thread local storage cleanup happening when the
27+
// main thread is exiting.
28+
//
29+
// The disadvantage of this workaround is that it means
30+
// it's not possible to "reload" a shared library but
31+
// we can cross that bridge when someone gets to it. :)
32+
//
33+
// Additional note: In theory `RTLD_NODELETE` should have
34+
// also worked as a workaround but it led to crashes.
35+
// (Also tried `RTLD_LOCAL` or `RTLD_FIRST` approaches.)
36+
//
37+
//
38+
// TODO: Document TLV on Mac issue with Library X.
39+
// TODO: Document at exit terminator issue on Linux with Library Y.
40+
//
41+
dlopen(path, RTLD_LAZY|RTLD_GLOBAL); // Workaround to bump ref-count so library never unloaded.
42+
return dlopen(path, RTLD_LAZY|RTLD_GLOBAL|RTLD_NOLOAD); // TODO: Is RTLD_LAZY the best?
1143
#else
1244
return LoadLibrary(path);
1345
#endif
@@ -25,6 +57,8 @@ const char *open_library_error() {
2557

2658
int close_library(HANDLE handle) {
2759
#ifdef IS_UNIX
60+
// Note: See workaround note in `open_library()` above as to why
61+
// the following line will no longer unload library.
2862
return dlclose(handle);
2963
#else
3064
return FreeLibrary((HMODULE) handle);

0 commit comments

Comments
 (0)