Bug 24427 – Crash when dlopen'ed library not dlclose'd explicitly

Status
NEW
Severity
major
Priority
P1
Component
druntime
Product
D
Version
D2
Platform
x86_64
OS
Linux
Creation time
2024-03-01T20:35:03Z
Last change time
2024-12-07T13:43:17Z
Assigned to
No Owner
Creator
Carl Sturtivant
Moved to GitHub: dmd#17475 →

Attachments

IDFilenameSummaryContent-TypeSize
1907main.cmain.ctext/plain1113
1908dynamic_lib.cdynamic_lib.ctext/plain129
1909main.dmain.dtext/plain1106
1910dynamic_lib.ddynamic_lib.dtext/plain148

Comments

Comment #0 by sturtivant — 2024-03-01T20:35:03Z
Compiling pure C (no D source) with dmd and using dynamic loading (not dynamic linking) causes a crash on program exit under certain conditions, where a gcc compilation of the same source works fine. Rewriting the C in D and compiling with dmd with identical switches causes the same crash. The following two examples are attached, using dlfcn.h from C source and core.sys.posix.dlfcn from D source. Both crash. A. ==== dmd -c main.c dmd -of=main -L-E main.o -L-ldl dmd -c -fPIC dynamic_lib.c dmd -of=dynamic_lib.so -shared -fPIC dynamic_lib.o ==== B. ==== dmd -c main.d dmd -of=main -L-E main.o -L-ldl dmd -c -fPIC dynamic_lib.d dmd -of=dynamic_lib.so -shared -fPIC dynamic_lib.o ==== A. and B. * main dynamically loads dynamic_lib.so * main calls a function in dynamic_lib.so which calls a function in main * main is linked with a switch to export all symbols so this works When A. is built with gcc it works fine. Failure to call dlclose before main exits causes the crash; main runs correctly before that. (If the commented out call of dlclose is made then everything works.) Crash: ==== $ main 1 2 3 4 Aborting from src/rt/sections_elf_shared.d(512) DSO being unregistered isn't current last one.Aborted (core dumped) ==== This crash occurs only if 1. Both main and dynamic_lib are built with dmd. (either from C source or D source) (If one of main, dynamic_lib.so is built with gcc, everything works.) 2. Main is NOT linked with -defaultlib=libphobos2.so (irrespective of how dynamic_lib is linked to phobos)
Comment #1 by sturtivant — 2024-03-01T20:37:14Z
Created attachment 1907 main.c
Comment #2 by sturtivant — 2024-03-01T20:37:54Z
Created attachment 1908 dynamic_lib.c
Comment #3 by sturtivant — 2024-03-01T20:38:43Z
Created attachment 1909 main.d
Comment #4 by sturtivant — 2024-03-01T20:39:15Z
Created attachment 1910 dynamic_lib.d
Comment #5 by alphaglosined — 2024-03-01T20:51:38Z
Just to clarify: Does a crash only occur when the executable has druntime linked in and initialized? If you load a shared library that has druntime linked in, does it also crash if you initialize druntime? Does this happen with ldc?
Comment #6 by sturtivant — 2024-03-01T21:50:35Z
1. lcd did not produce the bug, using --link-defaultlib-shared=false for both the main program and the dynamic library. 2. When the dynamic library C source is compiled and linked with -betterC the error does not occur. 3. It does crash with druntime initialized in the dynamic library.
Comment #7 by alphaglosined — 2024-03-01T21:54:15Z
When using ldc does it crash when druntime is a shared library and initialized? This will confirm that it is a druntime bug.
Comment #8 by sturtivant — 2024-03-01T22:01:52Z
> When using ldc does it crash when druntime is a shared library and initialized? Is this the default for ldc?
Comment #9 by alphaglosined — 2024-03-01T22:06:05Z
The default phobos/druntime shared/static may depend upon platform and distribution.
Comment #10 by sturtivant — 2024-03-01T22:54:36Z
(In reply to Richard Cattermole from comment #9) > The default phobos/druntime shared/static may depend upon platform and > distribution. I used the --link-defaultlib-shared=true option which I assume also shares druntime. I found no switch mentioning sharing or statically linking druntime explicitly. Neither main.c nor dynamic_lib.c will link with --link-defaultlib-shared=true With that false, the C version just works. By contrast, D source links for all four combinations of true/false for --link-defaultlib-shared for each build. Three work, one crashes. ==== $ ldc2 -c main.d $ ldc2 -of=main -L-E main.o -L-ldl --link-defaultlib-shared=false $ ldc2 -c --relocation-model=pic dynamic_lib.d $ + ldc2 -of=dynamic_lib.so -shared -relocation-model=pic dynamic_lib.o --link-defaultlib-shared=true $ main Aborting from rt/sections_elf_shared.d(605) Only one D shared object allowed for static runtime. Link with shared runtime via LDC switch '-link-defaultlib-shared'.Aborted (core dumped) ====
Comment #11 by sturtivant — 2024-03-01T23:09:23Z
(In reply to Carl Sturtivant from comment #10) > (In reply to Richard Cattermole from comment #9) ==== $ ldc2 -c main.d $ ldc2 -of=main -L-E main.o -L-ldl $ ldc2 -c --relocation-model=pic dynamic_lib.d $ ldc2 -of=dynamic_lib.so -shared -relocation-model=pic dynamic_lib.o (dmd-2.107.0)carl@palmtree ~/Documents/dprogs/dl $ main Aborting from rt/sections_elf_shared.d(605) Only one D shared object allowed for static runtime. Link with shared runtime via LDC switch '-link-defaultlib-shared'.Aborted (core dumped) ==== --- looks like the crash options are the default: not shared for main and shared for the dynamic library.
Comment #12 by alphaglosined — 2024-03-01T23:33:42Z
Okay, ldc and dmd have differing implementations of ``rt.sections_elf_shared``. With ldc yes, you need to stick with only shared library build of druntime, it cannot be mixed. From what I can tell it's an ordering problem due to not explicitly loading then unloading druntime in the right order.
Comment #13 by sturtivant — 2024-03-01T23:56:42Z
(In reply to Richard Cattermole from comment #12) > From what I can tell it's an ordering problem due to not explicitly loading > then unloading druntime in the right order. That's intuitively reasonable.
Comment #14 by robert.schadek — 2024-12-07T13:43:17Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/17475 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB