Within winpthreads, a native posix thread is a thread that has
been created via pthread_create.

Previously, pthread key destructors were executed immediately when
the thread exits, for native posix threads. For non-posix native
threads (i.e. threads created via some other API than pthreads),
the pthread key destructors were executed later, via the
__dyn_tls_pthread callback.

When a thread has got TLS objects, where the TLS implementation is
provided via emutls (compiled with the GCC posix thread model, which
uses winpthreads), the memory for those TLS objects is allocated
via emutls and gets deallocated via a pthread key destructor.

When the destructors of the TLS objects are executed via
mingw-w64-crt's __cxa_thread_atexit, those destructors are executed
via a TLS callback, after the point when emutls has deallocated
their storage memory.

To fix this, don't run the pthread key destructors immediately,
but later via the __dyn_tls_pthread callback, just like for non-posix
native threads. This makes sure the memory for the TLS objects isn't
freed at the time when the destructors are executed.

See also: https://bugreports.qt.io/browse/QTBUG-131476
---
To repro and analyze the situation, apply
https://github.com/mstorsjo/mingw-w64/commit/tls-winpthreads-log on
mingw-w64, and
https://github.com/mstorsjo/gcc/commit/log-emutls-thread-atexit
on gcc, and compile
https://martin.st/temp/tls-dtor.cpp.

Unfortunately, this isn't enough to fix all cases of this issue.
This patch fixes the case when winpthreads is statically linked
into the same executable as the user code destructors. If they
reside in a separate DLL, the winpthreads TLS callback executes
before the main executable TLS callbacks, so the emutls memory still
is freed before running the destructors.

Also for the case of having them statically linked, I guess there's
no guarantee about the order of the TLS callbacks between
mingw-w64-crt tls_atexit.c and winpthreads.
---
 mingw-w64-libraries/winpthreads/src/thread.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/mingw-w64-libraries/winpthreads/src/thread.c 
b/mingw-w64-libraries/winpthreads/src/thread.c
index 68858cfa6..3535797e3 100644
--- a/mingw-w64-libraries/winpthreads/src/thread.c
+++ b/mingw-w64-libraries/winpthreads/src/thread.c
@@ -456,9 +456,10 @@ __dyn_tls_pthread (HANDLE hDllHandle, DWORD dwReason, 
LPVOID lpreserved)
     {
       if (_pthread_tls != 0xffffffff)
        t = (_pthread_v *)TlsGetValue(_pthread_tls);
+      if (t)
+         _pthread_cleanup_dest (t->x);
       if (t && t->thread_noposix != 0)
        {
-         _pthread_cleanup_dest (t->x);
          if (t->h != NULL)
            {
              CloseHandle (t->h);
@@ -1566,8 +1567,6 @@ pthread_create_wrapper (void *args)
       #endif
       pthread_mutex_lock (&mtx_pthr_locked);
       tv->ret_arg = (void*) trslt;
-      /* Clean up destructors */
-      _pthread_cleanup_dest(tv->x);
     }
   else
     pthread_mutex_lock (&mtx_pthr_locked);
-- 
2.43.0



_______________________________________________
Mingw-w64-public mailing list
Mingw-w64-public@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

Reply via email to