Home > front end >  Throwing Clear Exception in a Multithreaded Context with a proram STOP
Throwing Clear Exception in a Multithreaded Context with a proram STOP

Time:01-15

I have a program that throws in another thread as follows:

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

void op()
{
    std::cout << "OP HELLO WORLD" << std::endl;
    throw(std::runtime_error("OP ERROR"));
};

int main(int argc, char* argv[])
{
    //throw(std::runtime_error("MAIN ERROR"));
    std::thread t(op);
    t.join();
    std::cout << "MAIN HELLO WORLD" << std::endl;
};

I want my program to print a clear error message and stop. I know I can use std::abort or std::terminate, however the error message is not clear and does not contain the log "OP ERROR".

Could you please help me code a program that when fails exits and logs a clear error message. std::future does not work too when I tried a try, catch block?

CodePudding user response:

To avoid the call to std::terminate, make sure exceptions don't "leak" outside the thread function.

void op()
{
    try {
        std::cout << "OP HELLO WORLD" << std::endl;
        throw std::runtime_error("OP ERROR");
    } catch (const std::exception& e) {
        std::cerr << "Exception: " << e.what() << std::endl;
        exit(1);
    }
}

If you want to automatically see the exception's file and line number, in C it is not generally possible.

If you want to catch all exceptions in a single place in the main thread, you need to catch them and pass them to the main thread. There's a useful wrapper utility std::packaged_task which gives back a future on which you can wait for the result or an exception.

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

void op()
{
    std::cout << "OP HELLO WORLD" << std::endl;
    throw std::runtime_error("OP ERROR");
}

int main(int argc, char* argv[])
{
    try {
        std::packaged_task<void()> task{&op};
        auto result = task.get_future();
        std::thread t{std::move(task)};
        t.join();
        result.get();
        std::cout << "MAIN HELLO WORLD" << std::endl;
    } catch (const std::exception& e) {
        std::cerr << "Exception: " << e.what() << std::endl;
    }
}

CodePudding user response:

Are you looking for something like this?

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

void op()
{
    std::cout << "OP HELLO WORLD" << std::endl;
    throw(std::runtime_error("OP ERROR. File: " __FILE__ ", Line: "  std::to_string(__LINE__)));
};

int main(int argc, char* argv[])
{
    //throw(std::runtime_error("MAIN ERROR"));
    auto res = std::async(op);
    try {
        res.get();
    } catch(const std::exception& e) {
        std::cerr << "Error: " << e.what() << std::endl;
        return -1;
    }
    std::cout << "MAIN HELLO WORLD" << std::endl;
}

If you want to output errors for all threads without returning exceptions to main thread, you can setup your own version of terminate().

#include <iostream>
#include <cstdlib>
#include <exception>
#include <thread>

void op()
{
    std::cout << "OP HELLO WORLD" << std::endl;
    throw(std::runtime_error("OP ERROR"));
}

void my_terminate()
{
    auto eptr = std::current_exception();
    try {
        if (eptr) {
            std::rethrow_exception(eptr);
        }
    } catch(const std::exception& e) {
        std::cerr << "Error: " << e.what() << std::endl;
    }
    std::abort();
}

int main(int argc, char* argv[])
{
    std::set_terminate(my_terminate);
    //throw(std::runtime_error("MAIN ERROR"));
    std::thread t(op);
    t.join();
    std::cout << "MAIN HELLO WORLD" << std::endl;
}

For some reason this didn't work with MSVC, though.

  • Related