user2997518
user2997518

Reputation: 852

throwing exception from thread is not giving expected results

In below code snippet i am trying to catch the exception after re-throwing the same but couldn't achieve the same . I am not sure what went wrong though as i already have preserved current teptr state through current_exception(). Thread is running in continuous loop so once its value reaches to the greater 2 then catch block is executed and control reaches out of the loop but still as expected i am not able to reach the other catch block in first attempt itself.

#include <boost/thread.hpp>
#include <boost/thread/scoped_thread.hpp>
#include <boost/chrono.hpp>
#include <iostream>
#include <boost/exception/all.hpp>
#include <exception>
using namespace std;
boost::exception_ptr teptr;

class myexception : public exception
{
    virtual const char* what() const throw()
    {
        return "My exception happened";
    }
} myex;

class ABC
{
public:
    void start();

};

void ABC::start()
{
    int i = 0;
    cout << "running the thread" << std::endl;

    while (1)
    {
        try
        {
            std::cout << "value of " << i << '\n';

            if (i > 2)
            {
                throw  boost::enable_current_exception(myex);
            }
            i++;
        }
        catch (exception& e)
        {
            cout << "actual exception is" << e.what() << '\n';
            teptr = boost::current_exception();
            break;
            //throw myex;
        }
    }
}

int main()
{
    ABC abc;
    boost::thread thread_point;

    while (1)
    {
        boost::thread thread_point;
        thread_point = boost::thread(&ABC::start, abc);

        if (teptr) {

            try {
                boost::rethrow_exception(teptr);
            }
            catch (const std::exception &ex)
            {
                std::cerr << "Thread exited with exception: " << ex.what() << "\n";
                exit(0);
            }
        }
    }
}

Upvotes: 1

Views: 135

Answers (2)

lakeweb
lakeweb

Reputation: 1939

Update My answer is deficient and with error, see sehe's comment.

I'm not sure what your end goal is here but to figure out how to handle a throw from a thread. Yes, you can get around the compilers inability to throw between threads with Boost Exception.

#include <boost/thread.hpp>
#include <boost/thread/scoped_thread.hpp>
#include <boost/chrono.hpp>
#include <iostream>
#include <boost/exception/all.hpp>
#include <exception>

boost::exception_ptr teptr;
class myexception: public std::exception
{
    virtual const char* what() const throw()
    {
        return "My exception happened";
    }
} myex;


class ABCc
{
public:
    void start();
};

void ABCc::start()
{  
    int i=0;
    std::cout<<"running the thread"<<std::endl;

    while (1)
    {
        try
        {
            std::cout << "value of "<<i << '\n';

            if(i>2)
            {
                throw  boost::enable_current_exception(myex);
            }
            i++;
        }
        catch (std::exception& e)
        {
            std::cout << "actual exception is"<<e.what() << '\n';
            teptr=boost::current_exception();
            break;
            // where were you going here???????
            //throw myex;
        } 
    }
}

int main()
{
    ABCc abc;
    boost::thread thread_point;
    thread_point = boost::thread(&ABCc::start,abc);
    while(1)
    {
        if (teptr) {
            try {
                boost::rethrow_exception(teptr);
            }
            catch(const std::exception &ex) {
                std::cerr << "Thread may have exited; exception thrown: " << ex.what() << "\n";
                break;
            }
        } 
    } 
    std::cout << "exception should have been caught" << std::endl;
    return 0;
}   

Note that you do not have to throw/catch in main. You were creating multiple threads by having boost::thread inside your loop, was that your intention?

Upvotes: 0

sehe
sehe

Reputation: 392921

Your program access the variable teptr (as well as myex) from multiple threads simultaneously without synchronization. The behaviour is UNDEFINED.

What's worse, you're shadowing thread_point and creating many threads that aren't joined. You're literally running unlimited threads sharing the same global data.

I suppose you're really looking for futures - that allow you to return a value or an exception from wherever. All the exception handling magic is done for you:

Live On Coliru

#include <thread>
#include <future>
#include <iostream>
#include <sstream>

struct ABC {
    int task(int until) {
        for (int i = 0; i<10; ++i) {
            if (i > until) {
                std::ostringstream oss;
                oss << "My exception happened in thread " << std::this_thread::get_id() << " at i=" << i;
                throw std::runtime_error(oss.str());
            }
        }

        return 42;
    }
};

int main() {
    for (int runs = 0; runs < 10; ++runs) {
        ABC abc;
        std::future<int> result = std::async(&ABC::task, &abc, rand()%20);

        try {
            std::cout << "Task returned " << result.get() << "\n";
        } catch (const std::exception &ex) {
            std::cout << "Task exited with exception: " << ex.what() << "\n";
            std::cerr << "Thread exited with exception: " << ex.what() << "\n";
        }
    }
}

Prints (e.g.):

Task returned Task exited with exception: My exception happened in thread 140288972076800 at i=4
Thread exited with exception: My exception happened in thread 140288972076800 at i=4
Task returned Task exited with exception: My exception happened in thread 140288972076800 at i=7
Thread exited with exception: My exception happened in thread 140288972076800 at i=7
Task returned 42
Task returned 42
Task returned 42
Task returned 42
Task returned Task exited with exception: My exception happened in thread 140288972076800 at i=7
Thread exited with exception: My exception happened in thread 140288972076800 at i=7
Task returned 42
Task returned 42
Task returned Task exited with exception: My exception happened in thread 140288972076800 at i=2
Thread exited with exception: My exception happened in thread 140288972076800 at i=2

Upvotes: 4

Related Questions