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

Jaap Geurts jaap.geurts at gmail.com
Mon Nov 20 23:03:43 UTC 2023


On Thursday, 16 November 2023 at 17:59:56 UTC, Arjan wrote:
> On Wednesday, 15 November 2023 at 22:41:19 UTC, Jaap Geurts 
> wrote:
>> I apologize if this has been asked before but I couldn't find 
>> help here or anywhere else.
>>
>> [...]
>
> I do not understand what you want to achieve, but maybe

I want to load a plugin into QML. This works with the help of 
dqml. It crashes upon exit of the QML app but I must have a clean 
exit. What I think happens is the following:

Qt loads the DSO (my plugin written in D). In an init routine I 
start the D runtime with `rt_init()`. This happens in a thread 
created by Qt which means that D will setup TLS or reuse existing 
TLS for that thread. Further the runtime keeps track of libraries 
which have been loaded. So when my plugin is loaded, the D 
runtime scans all segments looking for loaded libraries which 
were dynamically linked-in into my plugin. It then stores those 
pointers to the loaded libraries in a `__gshared` collection so 
that whenever another thread tries to open an already stored 
library, the runtime will return that pointer. The runtime also 
stores which libraries are available for each thread and it 
stores that for each thread individually in TLS space. What 
happens is this:

* At startup the `__gshared` library collection gets populated 
with pointers of already loaded libraries. Second the TLS 
collection of open libraries also gets setup for the current 
thread.
* At exit, when Qt quits the main thread(without properly 
unloading libraries or quitting other threads nicely), the D exit 
handler runs. It sees no library pointers in the collection in 
the current TLS space (because now it's looking in the TLS of 
`main()` but the `__gshared` collection still has references. 
Then it bugs out with a safeAbort saying that loading and 
unloading isn't synchronized. This is technically correct but not 
helpful.

The best solution for me would be that the D runtime would still 
report an error, but not call `abort()`.

> (ab)using the 
> [`atexit`](https://en.cppreference.com/w/cpp/utility/program/atexit)from the D shared object to register a function *in* the D shared object at app exit?
> Be-aware when [`dlclose`](https://linux.die.net/man/3/dlclose) 
> *is* used on the D shared object, the app will crash due to the 
> function-pointer pointing to already unmapped lib function is 
> called by `atexit`.

I tried this, but doesn't work either, because when I register my 
function I'm late to the party and my function gets called after 
D's runtime exit handler has been called. Even if I could 
intercept the call it still wouldn't work, because `atexit()` 
runs in the main thread and the current TLS library collection is 
empty and I can't unload the library because the `__gshared` 
collection is internal to D's runtime.

My code example above is a good explanation of what happens in my 
setup. It crashes with the exact same error message.

Thanks for taking the time to answer me.


More information about the Digitalmars-d mailing list