Bug 17696 – dlclose() not guaranteed to unload the library

Status
NEW
Severity
blocker
Priority
P1
Component
druntime
Product
D
Version
D2
Platform
All
OS
Linux
Creation time
2017-07-26T22:15:42Z
Last change time
2024-12-07T13:37:28Z
Assigned to
No Owner
Creator
Iain Buclaw
Moved to GitHub: dmd#17159 →

Comments

Comment #0 by ibuclaw — 2017-07-26T22:15:42Z
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
Comment #1 by ibuclaw — 2017-07-26T22:18:57Z
GCC internals note, there's flag_gnu_unique. But actually it seems pretty silly turning it off explicitly.
Comment #2 by ibuclaw — 2017-07-27T07:05:32Z
And on a D language implementation note, if you didn't use ClassInfo for setting the monitor in synchronized() statements, then I could have just marked the data as read-only.
Comment #3 by robert.schadek — 2024-12-07T13:37:28Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/17159 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB