Skip to content

TLS struct destructors not called when thread is not joined #10809

@yowl

Description

@yowl

With the following on Linux (or Windows Subsytem for Linux)/Ubuntu

#include <stdio.h>
#include <iostream>
#if EMSCRIPTEN
include <emscripten.h>
#else
#include <chrono>
#include <thread>
#endif

struct TlsDestructionMonitor
{
        public:
                  TlsDestructionMonitor() {
                          std::cout << "ctr " << std::uintptr_t(this);
                              printf("Constructor()\n");
                                }

        void Set()
        {
                printf("set\n");
        }

  ~TlsDestructionMonitor()
  {
    printf("dest\n");
  }
};

thread_local TlsDestructionMonitor tls_destructionMonitor;
void* doWork(void *arg)
{
        printf("thread doing work\n");
        tls_destructionMonitor.Set();
        return NULL;
}

int main()
{
        pthread_t thread;
        pthread_attr_t attr;
        void * retVal;

        printf("hello\n");
        int id = pthread_create(&thread, NULL, &doWork, NULL);
        if(!id)
        {
                printf("sleeping\n");
#if EMSCRIPTEN
                emscripten_sleep(1000);
#else
                std::this_thread::sleep_for(std::chrono::milliseconds(1000));
#endif
                printf("slept\n");
                //printf("joining\n");
                //                //pthread_join(thread, &retVal);
                //                                //printf("joined\n");
                                                                                                                        //                                        }
        }
        return(0);
}

Compile with
g++ 1.cpp -lpthread -pthread
and run
./a.out
and you get

hello
sleeping
thread doing work
ctr 140391460898558Constructor()
set
dest
slept

The dest is from the destructor of the struct. Same code with

em++ t.cpp -s USE_PTHREADS=1 -o t.html --emrun -s PROXY_TO_PTHREAD=1 -s ASYNCIFY=1

And run it in New Edge (Chrome backend) and you get

hello
sleeping
thread doing work
ctr 5398504Constructor()
set
slept

The destructor is not called. If you replace the main thread's sleep with a join it works the same on Linux and Emscripten.

Possibly related to #9251 although that's about exit and ending all threads.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions