I apologize if this has been asked before but I couldn't find help here or anywhere else.
I'm trying to load my code as a dynamic library in a C++ program. It is working, but I have a problem upon program exit with thread local storage.
What I'm trying to do:
The c++ loads my dynamic library from a thread (not the main thread) and when the application exits from the main thread (without properly unloading the library), the finalizers run in the main thread and do not know about the loaded library (because it's kept in TLS _loadedDSOs
in the thread that loaded the library) but the handle to the library is recorded in __global _handleToDSOs
. When the main thread exits the loaded libraries is compared to the open handles. Since the main thread thinks nothing is loaded (_loadedDSOs
is empty) the code aborts because the handle _handleToDSOs
is not empty. This causes the d runtime to abort. I've reduced the problem to this example code:
#include <dlfcn.h>
#include <pthread.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void* loadlib(void*);
void main()
{
int counter = 0;
pthread_t thread1;
pthread_attr_t attrs;
pthread_attr_init(&attrs);
pthread_create(&thread1, &attrs, &loadlib, NULL);
while (true) {
printf("Main %d\n", counter++);
usleep(300000);
if (counter == 5)
break;
}
}
void* loadlib(void* args)
{
int counter = 100;
void* dlib = dlopen("libdlibrary.so", RTLD_LAZY | RTLD_GLOBAL);
if (dlib == NULL) {
printf("Can't open dlib\n");
exit(0);
}
void (*dfunc)() = dlsym(dlib, "dfunc");
dfunc();
while (true) {
printf("Thread %d\n", counter++);
usleep(700000);
}
}
Compile with cc -o app app.c
And the D code as a library
import std.stdio;
import core.runtime;
extern (C) void dfunc() {
writeln("Hello from D");
// rt_init();
}
Compile with: ldc2 -shared dlibrary.d
And run the app with: LD_LIBRARY_PATH=. ./app
This causes the crash.
I realize that this is not the correct way to do things, but the problem is, I can't change the way the C++ program works which is: It loads my library from a thread, but when it exits, it just quits the main thread. Things I can't do on the C++ program:
- load the lib from the main thread. (My code is a plugin which only becomes active when it is being loaded by the thread)
- gracefully stop the thread that loaded the library and unload the library
- the c++ program never unloads the lib so pragma(crt_destructor) doesn't work either
- rt_init() doesn't help either.
Is there anything I can do to fix this issue on the D side?
Help would be greatly appreciated!