Qiao
Qiao

Reputation: 512

Is it possible to catch a exception of unjoined thread termination in c++?

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

Answers (2)

Aykhan Hagverdili
Aykhan Hagverdili

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

gerum
gerum

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

Related Questions