Current-Users archive

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

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

On Mon 29 Jun 2020 at 09:55:10 +0200, Rhialto wrote:
> I've looked at __cxa_finalize a bit better, and it seems that the lock
> mutex_lock(&__atexit_mutex); isn't just used to protect running the
> atexit handlers, but even to protect looking at the list of handlers:
> atexit_handler_stack.
> So the fact that libavformat establishes a handler may be a red herring.
> I will try to test this later today somehow.

So I did a small experiment. Since VICE dlopens several of the ffmpeg's
shared libraries, I changed the order that it is closing them. I get

ffmpegdrv_shutdown: entered; calling ffmpeglib_close(&ffmpeglib);
ffmpeglib_close: free_avcodec()
vice_dynlib_close: pthread=0x72abf78b8000
ffmpeglib_close: free_avutil()
vice_dynlib_close: pthread=0x72abf78b8000
ffmpeglib_close: free_swscale()
vice_dynlib_close: pthread=0x72abf78b8000
^C^\Quit (core dumped)

meaning that it managed to dlclose libavcodec, libavutil, and hangs
during libswscale. None of those contain calls to atexit that I could
find in the source; only libavformat/avisynth.c refers to atexit.

With my revised chain of events, I was expecting that it would deadlock
while dlclosing the first shared library, which is now libavcodec.

Instead it deadlocks at the third. I'm not sure yet what to make of
that. I can only say that in gdb, breaking on __cxa_finalize, the first
two libraries don't seem to get there at all and the first library to
get there is 

Thread 9 "" hit Breakpoint 2, __cxa_finalize (                                  
    dso=0x7b02ccc7b940 <__dso_handle>) at /usr/src/lib/libc/stdlib/atexit.c:192 
(gdb) bt                                                                        
#0  __cxa_finalize (dso=0x7b02ccc7b940 <__dso_handle>)                          
    at /usr/src/lib/libc/stdlib/atexit.c:192                                    
#1  0x00007b02cca02318 in ?? () from /usr/pkg/lib/ffmpeg4/       
#2  0x00007b02e49fe1a0 in ?? ()                                                 
#3  0x00007b02cca6c579 in _fini () from /usr/pkg/lib/ffmpeg4/    
#4  0x0000000000000000 in ?? ()                                                 

I'm not sure why this library has a _fini() function which gets called.

This would make the chain of events (3rd version):

1. In the original thread, it dlopen()s a library with a _fini function
   which calls __cxa_finalize(). [what causes this???]
2. There is no 2.
3. The main thread starts a new thread, and registers an atexit()
   handler to clean up that thread.
3a. Both threads run for a while doing their main jobs.
4. main thread exit()s.
5. atexit() handler obtains its lock (which protects the handler list),
   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. __cxa_finalize() gets called on behalf of the library, which tries to
  obtain the same lock that was already obtained, in a different thread,
  in step 5.
8. deadlock.

In this case, the fault cannot be with libavformat or libswscale, right?

Olaf 'Rhialto' Seibert -- rhialto at falu dot nl
___  Anyone who is capable of getting themselves made President should on
\X/  no account be allowed to do the job.       --Douglas Adams, "THGTTG"

Attachment: signature.asc
Description: PGP signature

Home | Main Index | Thread Index | Old Index