Reputation: 512
I have a thread running in an endless loop to do some work. Now I want to terminate the program smoothly without any error, is it possible to just terminate the thread without join and just catch the exception?
I tried the following code:
#include <iostream>
#include <thread>
#include <chrono>
#include <memory>
using namespace std;
void foo()
{
// simulate expensive operation
this_thread::sleep_for(chrono::seconds(1));
}
void bar()
{
// simulate expensive operation
while (true)
this_thread::sleep_for(chrono::seconds(1));
}
int main()
{
cout << "starting first helper...\n";
thread helper1(foo);
cout << "starting second helper...\n";
shared_ptr<thread> helper2 = make_shared<thread>(bar);
cout << "waiting for helpers to finish..." << endl;
helper1.join();
try {
helper2.reset(); // drop thread without join
} catch (exception e) {
cout << e.what() << endl;
}
cout << "done!\n";
}
And I got following result:
starting first helper...
starting second helper...
waiting for helpers to finish...
terminate called without an active exception
Aborted (core dumped)
Looks like there's no exception thrown. Why?
Upvotes: 0
Views: 724
Reputation: 30005
Instead of a while (true)
you can pass in an atomic bool, which the main thread changes when it wants to exit, and joins the thread:
#include <atomic>
#include <chrono>
#include <cstdio>
#include <thread>
void expensive_func() {
std::puts("Start expensive_func");
std::this_thread::sleep_for(std::chrono::seconds(1));
std::puts("End expensive_func");
}
void daemon(std::atomic<bool> const* running) {
while (*running) {
expensive_func();
}
}
int main() {
std::atomic<bool> running = true;
std::thread worker(daemon, &running);
// Do something
std::this_thread::sleep_for(std::chrono::seconds(5));
// Done, let the thread know that we're done
running = false;
// Join the worker
worker.join();
}
You can also wrap this whole thing in a DaemonThread
class, so the cleanup happens automatically and it's exception-safe.
Upvotes: 1
Reputation: 1144
No you can not because it is not an exception, the threads destructor calls std::terminate direct.
A way around this depends on what you want. If you use jthread instead of thread, the destructor will call join itself. If you do not need access to the thread anymore, you can detach the thread before destructing it.
Upvotes: 2