runtime crashes with "rt/sections_elf_shared.d(688) _handleToDSO not in sync with _loadedDSOs"

Jaap Geurts jaap.geurts at gmail.com
Wed Nov 15 22:41:19 UTC 2023


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:

1. load the lib from the main thread. (My code is a plugin which 
only becomes active when it is being loaded by the thread)
2. gracefully stop the thread that loaded the library and unload 
the library
3. the c++ program never unloads the lib so 
pragma(crt_destructor) doesn't work either
4. 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!



More information about the Digitalmars-d mailing list