Current-Users archive

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

Re: atexit(), dlclose() and more atexit()



On Sun, Jun 28, 2020 at 10:56:01PM +0200, Rhialto wrote:
> On Sun 28 Jun 2020 at 22:39:28 +0200, Joerg Sonnenberger wrote:
> > On Sun, Jun 28, 2020 at 10:35:27PM +0200, Rhialto wrote:
> > > I have at hand a program (the current svn trunk of VICE, to be exact)
> > > which does the following:
> > > 
> > > 1. In the original thread, it dlopen()s libavformat.
> > > 2. libavformat establishes an atexit() handler.
> > > 3. The main thread starts a new thread, and registers an atexit()
> > >    handler to clean up that thread.
> > > 4. main thread exit()s.
> > > 5. atexit() handler obtains its lock, and calls the handler established in 3.
> > > 6. said handler tells the new thread to clean up and finish. One of the last
> > >    things the thread does, is to dlclose() libavformat.
> > > 7. libavformat's atexit handling gets called, which tries to obtain the
> > >    same lock that was already obtained, in a different thread, in step
> > >    5.
> > > 8. deadlock.
> > > 
> > > Who is in the wrong here?
> > 
> > libavformat. Never use atexit() with a handler in a library that can be
> > closed.
> 
> The funny thing is that libavformat uses an atexit handler due to issues
> with dynamic (un)loading (or so they claim). This is from their file
> ffmpeg-4.2.2/libavformat/avisynth.c:
> 
> /* A conflict between C++ global objects, atexit, and dynamic loading requires
>  * us to register our own atexit handler to prevent double freeing. */

It is fundamentally wrong to use a handler in a library that can be
unloaded. Some systems hack around that problem by looping over all
atexit handlers on dlclose, but that's exactly that, a costly hack. The
most common way this triggers is a segfault, actually.

The code should be using either a C dtor with the appropiate attribute
or __cxa_atexit directly, but the former is preferable.

Joerg


Home | Main Index | Thread Index | Old Index