Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 536
Vittorio Romeo Avatar asked Aug 30 '13 19:08

Vittorio Romeo


People also ask

What happens when you detach a thread?

Detaching ThreadsSeparates the thread of execution from the thread object, allowing execution to continue independently. Any allocated resources will be freed once the thread exits.

How do you stop a detached thread?

In C++, once the thread is detached or uses the detach() function, then we cannot stop such threads, and still, if there is a need for stopping such threads, then only one way is to return the thread from the initial thread function by instantiating it in main() function, adding the Boolean value but before exiting ...

Can a detached thread be joined?

When a thread is created, one of its attributes defines whether it is joinable or detached. Only threads that are created as joinable can be joined. If a thread is created as detached, it can never be joined.

What happens if a thread is not joined?

If you don't join these threads, you might end up using more resources than there are concurrent tasks, making it harder to measure the load. To be clear, if you don't call join , the thread will complete at some point anyway, it won't leak or anything.


1 Answers

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()

like image 76
user123 Avatar answered Sep 27 '22 20:09

user123