tech-x11 archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: Lua shared object asymmetry loading Xlib.



On Sun, January 20, 2019 11:27 am, Joerg Sonnenberger wrote:
> On Sun, Jan 20, 2019 at 11:29:29AM +0100, Marc Balmer wrote:
>
>>
>>
>>> Am 20.01.2019 um 11:14 schrieb Kamil Rytarowski <n54%gmx.com@localhost>:
>>>
>>>
>>> On 20.01.2019 11:03, Martin Husemann wrote:
>>>
>>>> On Sun, Jan 20, 2019 at 10:32:43AM +0100, Kamil Rytarowski wrote:
>>>>
>>>>> I find it as workaround of our libc behavior.
>>>>>
>>>>
>>>> I disagree, there is no clean way to implement the call-on-dlclose
>>>> semantics (i.e. it needs disgusting ld.elf_so hacks and layer
>>>> violations).
>>>>
>>>> But maybe we should document the __cxa_atexit interface or provide
>>>> a public version?
>>>>
>>>
>>> libc++abi does not support a public interface to __cxa_atexit.
>>>
>>> It's also documented as being an internal API, so in my opinion
>>> without need for a documentation.  It could be mentioned in atexit(3).
>>>
>>
>>
>> One could argue that libraries should not use atexit() at all, but use
>> _fini() to their clean up tasks.  Dunno hwo portable that is, however.
>>
>
> That's essentially one of the two suggestion options. Using a global
> destructor or using __cxa_atexit.
>
> Joerg

I've definitely learned a bit over this.  It turns out to be a non-trivial
issue that transcends the original problem.

Having had an offline discussion with Christos and looking over what he did
to fix it, I see that this is more than a lua/Xlib problem.

The offending code were calls to free heap that was allocated for strings.
Simple enough, if it were not in a shared object.  Christos changed the
atexit code to __attribute__((destructor)).  This is the, so called,
standard way to do this, _init and _fini having been deprecated. Glibc
maintains a separate list of atexit addresses for DSOs and calls them at
dlclose time.  You can read about it:

http://man7.org/linux/man-pages/man3/dlopen.3.html

__attribute__((destructor)) is obviously a GCC extension.  Perhaps, in due
course, standards organizations will adopt a compatible scheme for compliant
implementations. Whether we will adopt the convention of maintaining
separate atexit lists for DSOs is a design question beyond my station.

I will make a few points.  First, heap must be used with extreme care in
DSOs.  It's one thing to allocate and hang on to the address within the
DSO, then free it during dlcose().  There is the other, more difficult
case, where the DSO allocates the storage and passes the address up to the
main program or to another DSO.  This is discussed a bit in the POSIX
standard:

http://pubs.opengroup.org/onlinepubs/9699919799/functions/dlclose.html

In order to make it work right the loader will have to keep track of each
heap address in the DSO and determine if it is also referenced elsewhere.
The only other option is to maintain separate heaps for each DSO and a
global heap for the main body of the program.  The decision then becomes,
which heap should I malloc from.

Nether of these is likely to be implemented soon.

For now we are stuck with  __attribute__((destructor)), until a standard
DSO initialization and finalization scheme is published.  The only other
way to go is to adopt the glibc setup where separate atexit lists are
maintained.  Nether of these solves the dangling heap address problem.

The take away is to use heap with care, if at all, in a DSO.  One more
argument for functional programming with garbage collection I suppose.

My hope is that agreement can be reached the about behavior of atexit,
and/or a POSIX way to initialize and finalize a DSO.

Thanks for all the attention to this.  And a further thanks to Christos,
for making it possible to continue working on what I started.

pjr



Home | Main Index | Thread Index | Old Index