www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 17696] New: dlclose() not guaranteed to unload the library

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: nobody puremagic.com
          Reporter: ibuclaw 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

--
Jul 26 2017