Issue 17696 - dlclose() not guaranteed to unload the library
Summary: dlclose() not guaranteed to unload the library
Status: NEW
Alias: None
Product: D
Classification: Unclassified
Component: druntime (show other issues)
Version: D2
Hardware: All Linux
: P1 blocker
Assignee: No Owner
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2017-07-26 22:15 UTC by Iain Buclaw
Modified: 2024-12-07 13:37 UTC (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Iain Buclaw 2017-07-26 22:15:42 UTC
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 Iain Buclaw 2017-07-26 22:18:57 UTC
GCC internals note, there's flag_gnu_unique.  But actually it seems pretty silly turning it off explicitly.
Comment 2 Iain Buclaw 2017-07-27 07:05:32 UTC
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 dlangBugzillaToGithub 2024-12-07 13:37:28 UTC
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