Reputation: 852
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
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
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 future
s - that allow you to return a value or an exception from wherever. All the exception handling magic is done for you:
#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