Comment #0 by john.loughran.colvin — 2019-09-27T09:38:47Z
% cat modcon.d
import modcon2;
void main()
{
import core.runtime : Runtime;
import core.sys.posix.dlfcn;
import std.stdio;
writeln("HI");
assert(Runtime.loadLibrary("./libmodcon2.so"));
}
% cat modcon2.d
__gshared int a;
shared static this() { foo(); }
void foo()
{
import core.stdc.stdio;
printf("%p ", &a);
printf("%p\n", &foo);
}
% dmd -shared modcon2.d -of=libmodcon2.so
% dmd -defaultlib=libphobos2.so modcon.d modcon2.d
% ./modcon
0x7f920f3a2140 0x7f920f39f930
HI
0x7f920f3a2140 0x7f920f39f930
As you can see from the printed pointers, the module constructor from the executable is called twice - once on process start and once on loading the shared library - and the module constructor from the shared library is never called.
Module constructors are normally designed to be called only once, so this causes some havok
Comment #1 by kinke — 2021-07-05T07:55:06Z
This 'works' with LDC v1.27 (but DMD v2.097 still fails):
0x55debef38074 0x55debef34090
HI
0x7fdfb6c12064 0x7fdfb6c10870
I think this is more likely related to compiler differences wrt. relocation model, not a druntime divergence.
Comment #2 by kinke — 2021-07-29T16:11:06Z
Further tests have shown that with DMD, the ModuleInfos of modules contained in both executable and library are apparently resolved to the executable's.
E.g., versioning out the module ctor in `modcon2.d` for the library still leads to it being invoked when loading the library; the opposite case, versioning it out for the executable, means it's not invoked at all.
Comment #3 by kinke — 2021-07-29T16:36:54Z
There's a related issue regarding CRT ctors - if both executable and library contain an identically mangled `pragma(crt_constructor)` function (doesn't even need to be in the same module - and name collision is quite likely due to the `extern(C)` requirement...), the executable one is invoked twice. Again DMD-specific, works with LDC.
Comment #4 by robert.schadek — 2024-12-13T19:05:43Z