Reputation: 93254
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?
Upvotes: 8
Views: 4189
Reputation:
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.
Upvotes: 8
Reputation: 9071
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()
Upvotes: 13