On 6/25/21 10:55 AM, Ali Çehreli wrote:
>I need your help with sporadic segfaults.
Players:
-
dmd 2.096 (but I've seen similar issues in the past with earlier versions as well)
-
A D library with extern(C) functions that calls rt_init() and rt_term(), which I think are needed for the library's use with Python
-
A D program that uses said library (would calling rt_init() and rt_term() cause harm in this case?) (Using the library with Python works fine.)
rt_init and rt_term are reentrant, you can call rt_term and rt_init as many times as you like, as long as you call rt_init first, and rt_term as many times as you called rt_init.
>The segfault happens when the program is shutting down. Here is a stack trace from a core dump:
[Current thread is 1 (Thread 0x7fb1ef95e700 (LWP 20010))]
(gdb) bt
#0 0x00007fb240a1c698 in _D2rt5minfo__T17runModuleFuncsRevSQBgQBg11ModuleGroup11runTlsDtorsMFZ9__lambda1ZQCoMFAxPyS6object10ModuleInfoZv () from /usr/lib/x86_64-linux-gnu/libphobos2.so.0.96
#1 0x00007fb240a1c0b1 in rt.minfo.ModuleGroup.runTlsDtors() () from /usr/lib/x86_64-linux-gnu/libphobos2.so.0.96
#2 0x00007fb240a1c411 in _D2rt5minfo16rt_moduleTlsDtorUZ14__foreachbody1MFKSQBx19sections_elf_shared3DSOZi () from /usr/lib/x86_64-linux-gnu/libphobos2.so.0.96
#3 0x00007fb240a1ddf2 in _D2rt19sections_elf_shared3DSO14opApplyReverseFMDFKSQByQByQBgZiZi () from /usr/lib/x86_64-linux-gnu/libphobos2.so.0.96
#4 0x00007fb240a1c3f1 in rt_moduleTlsDtor () from /usr/lib/x86_64-linux-gnu/libphobos2.so.0.96
#5 0x00007fb240a0a401 in thread_entryPoint () from /usr/lib/x86_64-linux-gnu/libphobos2.so.0.96
#6 0x00007fb23fcf56db in start_thread (arg=0x7fb1ef95e700) at pthread_create.c:463
#7 0x00007fb23f80671f in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
Hm... maybe try compiling Phobos/druntime in debug mode. Line numbers would be helpful.
It's interesting though, the segfault is not happening in a static destructor, but rather the function that runs the destructors (seems like a nested function).
Have you tried running demangle on these to see what they really are?
>If related, here are the library initialization and deinitialization functions, which I think are needed e.g. for using from Python:
// The initialization function of the library
pragma (crt_constructor)
extern (C)
void lib_init() {
const err = rt_init();
enum success = 1; // Yes, backwards.
if (err != success) {
fprintf(core.stdc.stdio.stderr, "Failed to initialize D runtime.");
abort();
}
}
// The deinitialization function of the library
pragma (crt_destructor)
extern (C)
void lib_deinit() {
const err = rt_term();
enum success = 1; // Yes, backwards.
if (err != success) {
fprintf(core.stdc.stdio.stderr, "Failed to deinitialize D runtime.");
// Intentionally not aborting in a destructor.
}
}
The segmentation fault is sporadic; likely due to a race condition. Is it related to my code? Can I workaround this? Can I reduce the likelihood of this happening?
Are you running any other CRT destructors that might use D constructs? Note that CRT destructors and constructors do not run in any specific order, unlike D constructors and destructors.
>The couple of places where I define any '~this' function is not used in this program. So, I rule out my allocating memory in a destructor.
Allocating memory in a destructor would not cause this problem.
-Steve