https://issues.dlang.org/show_bug.cgi?id=17696
Issue ID: 17696 Summary: dlclose() not guaranteed to unload the library Product: D Version: D2 Hardware: All OS: Linux Status: NEW Severity: blocker Priority: P1 Component: druntime Assignee: nob...@puremagic.com Reporter: ibuc...@gdcproject.org There's a broken test in druntime. Discovered after making a change in gdc to put ClassInfo symbols in the comdat (yeah I know, but I am yet to receive any duplicate symbol bug reports). https://github.com/dlang/druntime/blob/master/test/shared/src/load.d#L136-L139 Old gdc behaviour: --- $ readelf -Ws lib.o | grep MyFinal 113: 000000000000078a 38 FUNC GLOBAL DEFAULT 16 _D3lib11MyFinalizer6__dtorMFZv 117: 0000000000000000 16 OBJECT GLOBAL DEFAULT 28 _D3lib11MyFinalizer6__initZ 118: 0000000000000010 40 OBJECT GLOBAL DEFAULT 28 _D3lib11MyFinalizer6__vtblZ 119: 0000000000000000 152 OBJECT GLOBAL DEFAULT 30 _D3lib11MyFinalizer7__ClassZ 125: 0000000000000040 4112 OBJECT GLOBAL DEFAULT 28 _D3lib14MyFinalizerBig6__initZ 126: 0000000000001050 40 OBJECT GLOBAL DEFAULT 28 _D3lib14MyFinalizerBig6__vtblZ 127: 00000000000000a0 152 OBJECT GLOBAL DEFAULT 30 _D3lib14MyFinalizerBig7__ClassZ --- New gdc behaviour: --- $ readelf -Ws lib.o | grep MyFinal 124: 000000000000078a 38 FUNC GLOBAL DEFAULT 22 _D3lib11MyFinalizer6__dtorMFZv 128: 0000000000000000 16 OBJECT WEAK DEFAULT 34 _D3lib11MyFinalizer6__initZ 129: 0000000000000000 40 OBJECT WEAK DEFAULT 38 _D3lib11MyFinalizer6__vtblZ 130: 0000000000000000 152 OBJECT UNIQUE DEFAULT 36 _D3lib11MyFinalizer7__ClassZ 136: 0000000000000000 4112 OBJECT WEAK DEFAULT 40 _D3lib14MyFinalizerBig6__initZ 137: 0000000000000000 40 OBJECT WEAK DEFAULT 44 _D3lib14MyFinalizerBig6__vtblZ 138: 0000000000000000 152 OBJECT UNIQUE DEFAULT 42 _D3lib14MyFinalizerBig7__ClassZ --- Current dmd behaviour: --- $ readelf -Ws lib.o | grep MyFinal 105: 0000000000000000 34 FUNC GLOBAL DEFAULT 70 _D3lib11MyFinalizer6__dtorMFZv 106: 0000000000000000 16 OBJECT WEAK DEFAULT 72 _D3lib11MyFinalizer6__initZ 107: 0000000000000000 168 OBJECT WEAK DEFAULT 73 _D3lib11MyFinalizer7__ClassZ 108: 0000000000000000 40 OBJECT WEAK DEFAULT 75 _D3lib11MyFinalizer6__vtblZ 109: 0000000000000000 4112 OBJECT WEAK DEFAULT 78 _D3lib14MyFinalizerBig6__initZ 110: 0000000000000000 176 OBJECT WEAK DEFAULT 79 _D3lib14MyFinalizerBig7__ClassZ 111: 0000000000000000 40 OBJECT WEAK DEFAULT 81 _D3lib14MyFinalizerBig6__vtblZ --- Notice that dmd marks the __Class symbol as a weak @object, but gdc marks it as a weak @gnu_unique_object. This subtle difference means that when calling dlopen() on lib.so, it is marked as DF_1_NODELETE - meaning "not unloadable", and will never be unloaded no matter how many times you call dlclose(). Looking at the documentation: http://pubs.opengroup.org/onlinepubs/007904975/functions/dlclose.html === Although a dlclose() operation is not required to remove structures from an address space, neither is an implementation prohibited from doing so. === The druntime test should probably be fixed up, as it may not necessary always be true. In the meantime, I'll have a look at possibly a fix on my side, something that errs towards --no-gnu-unique, however if its not an agnostic fix, then there's no point in trying to do that. https://cygwin.com/ml/binutils/2011-10/msg00276.html --