std::thread::detach causes crash after original caller is destroyed

4k views Asked by At
struct Test {
    bool active{true};

    void threadedUpdate() {
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
        if(!active) // crashes here after Test instance is destroyed
            return; 
    }

    Test() { 
        std::thread([this]{ while(true) threadedUpdate(); }).detach();
    }

    ~Test() { 
        // somehow stop the detached thread?
    } 
};

When an instance of Test is initialized, it spawns and detaches an std::thread which runs in background. When the same instance is destroyed, the previously mentioned thread tries to access the active member, which was destroyed along with the instance, causing a crash (and an AddressSanitizer backtrace).

Is there a way to stop the detached thread on ~Test()?

The design is bad. How should a thread running in background until the caller is destroyed be spawned/handled correctly?

2

There are 2 answers

3
user123 On BEST ANSWER

Make the thread a member of the class, and instead of detaching it in the constructor, join it in the destructor. To stop the thread from looping, you can have a boolean inside the class that signals whether the thread should continue running or not (std::atomic<bool> update).

The thread could be executing this: [this] { while (update) threadUpdate(); }.

In the destructor of your class, do update = false, and call thread.join()

3
AudioBubble On

You can't stop detached threads. That's the point of .detach() - you don't have any way to refer to the detached thread anymore, at least as far as the C++ standard specifies. If you want to keep a handle to the thread, store the std::thread and call .join() in the destructor.