Hello,
I posted this issue on the gcc bug tracker, but I am not entirely sure if this is supposed to be a GCC bug or a mingw bug.
I see it has also been reported here, however at the moment I can not create a sourceforge account to comment on that. I apologize if this is not the proper place.
The issue here, to my best understanding, is the following.
-
At the very first access of a thread-local object in a new program, emutls_init is called via __emutls_get_address. This function allocates some memory for the storage using malloc (see emutls_alloc), and registers emutls_destroy to be executed at thread exit, using __gthread_key_create.
-
Immediately after, the TLS init function (generated by GCC) is called. This calls the C++ constructor on the storage provided at the previous point. It also uses __gthread_key_create to register the C++ destructor for execution at thread exit.
-
When a thread terminates, _pthread_cleanup_dest in winpthread is called. This function is responsible for calling all the destructors registered with pthread_key_create. Unfortunately, the execution order of such destructors is unspecified. In this case, it happens that emutls_destroy is called before the C++ destructor, which then executes on deallocated memory.
A quick workaround would be to reverse the loop in winpthread/src/thread.c:842. This will cause the destructors to be called in reverse order, and it will probably work correctly in most of the cases.
The only other solution would be to merge emutls+TLS init on GCC side, in such a way to have a single destructor callback to both invoke the C++ destructor and cleanup the memory.
Hello,
I posted this issue on the gcc bug tracker, but I am not entirely sure if this is supposed to be a GCC bug or a mingw bug.
I see it has also been reported here, however at the moment I can not create a sourceforge account to comment on that. I apologize if this is not the proper place.
The issue here, to my best understanding, is the following.
At the very first access of a thread-local object in a new program,
emutls_initis called via__emutls_get_address. This function allocates some memory for the storage usingmalloc(seeemutls_alloc), and registersemutls_destroyto be executed at thread exit, using__gthread_key_create.Immediately after, the
TLS init function(generated by GCC) is called. This calls the C++ constructor on the storage provided at the previous point. It also uses__gthread_key_createto register the C++ destructor for execution at thread exit.When a thread terminates,
_pthread_cleanup_destin winpthread is called. This function is responsible for calling all the destructors registered withpthread_key_create. Unfortunately, the execution order of such destructors is unspecified. In this case, it happens thatemutls_destroyis called before the C++ destructor, which then executes on deallocated memory.A quick workaround would be to reverse the loop in winpthread/src/thread.c:842. This will cause the destructors to be called in reverse order, and it will probably work correctly in most of the cases.
The only other solution would be to merge emutls+TLS init on GCC side, in such a way to have a single destructor callback to both invoke the C++ destructor and cleanup the memory.