jonnew
jonnew

Reputation: 194

std::thread and exception handling

I am having an issue handling exceptions in multithreaded c++ code. The following program exits with terminate called without an active exception Aborted (core dumped).

#include <thread>
#include <iostream>
#include <stdexcept>

struct Thing {

    void runComponent()
    {
       throw std::runtime_error("oh no!\n");
    }

    void runController()
    {
        while (true) {}
    }

    void run()
    {
        auto control_thread = std::thread([this] { runController(); });

        runComponent();

        if (control_thread.joinable())
            control_thread.join();
    }
};

int main() 
{
    try {
        Thing thing;
        thing.run();
    } catch (std::runtime_error &ex) {
        std::cerr << ex.what();
    }
}

Instead, I would like to handle the exception in the try catch block in main(). I understand that exceptions are not (normally) passed between threads since threads each have there own stack. The issue here (it seems to me) is that the exception is not being handled even though it is being generated on the non-forked thread. If I comment out the lines in run() having to do with control_thread, everything works fine.

Compiled with clang-3.8 and -std=c++11 main.cpp -lpthread.

Upvotes: 4

Views: 16259

Answers (1)

Curious
Curious

Reputation: 21510

The issue here is that you are neither calling detach() or join() on the thread you create in the run() method. That is an error in C++ threads. See When should I use std::thread::detach?

If you change your code to either of the following then everything works fine

#include <thread>
#include <iostream>
#include <stdexcept>

struct Thing {

    void runComponent()
    {
       throw std::runtime_error("oh no!\n");
    }

    void runController()
    {
        return;
    }

    void run()
    {
        auto control_thread = std::thread([this] { runController(); });
        // either of the following two will work
        // control_thread.join();
        control_thread.detach();

        runComponent();
    }
};

int main()
{
    try {
        Thing thing;
        thing.run();
    } catch (std::runtime_error &ex) {
        std::cerr << ex.what();
    }
}

It looked like what you wanted was a detach, thats why I detached the thread in the example above. If that is not what you want, you likely would need some other way to handle the join()ing of the thread. If you want the main thread and the other thread to function independently then you will need some other synchronization.

Upvotes: 4

Related Questions