Exit program when catch exception from thread - c++

Referring to Catching exception from worker thread in the main thread, I created a worker thread that throws exception to main thread and then terminates the program (the logic is to exit program upon exception happens).
I didn't seems to be implementing it correctly, as the program won't execute till the line where exit() was called.
Sample code:
#include <thread>
#include <iostream>
#include <stdexcept>
static std::exception_ptr _exceptionPtr = nullptr;
struct WorkerThread
{
std::thread thread;
void doSomething()
{
int seconds = 0;
bool shouldStop = false;
while(shouldStop == false)
{
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
std::cout << "time passed : " << ++seconds << "seconds" << std::endl;
if (seconds == 10) // something bad happened 10 seconds later
{
try
{
shouldStop = true;
throw std::runtime_error("something really bad happened");
}
catch (const std::runtime_error &ex)
{
_exceptionPtr = std::current_exception();
}
}
}
}
void run()
{
thread = std::thread([this] { doSomething(); });
thread.detach();
}
};
int main(int argc, char *argv[])
{
WorkerThread workerThread;
try
{
workerThread.run();
}
catch (...)
{
if (_exceptionPtr)
{
try
{
std::rethrow_exception(_exceptionPtr);
}
catch (std::runtime_error &ex)
{
// terminates program if exception happens
std::cout << "Program will now exit" << std::endl;
exit(EXIT_FAILURE); // but program never executes till here
}
}
}
for (;;)
{
// do A
// do B
// do C
// do ...
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
std::cout << "waiting for thread..." << std::endl;
}
return 0;
}
What did i miss ? Is the current approach correct ? If no, how do i do it correctly ? thanks

In the code you posted, the exception check is happening only once, and possibly before the thread has been launched.
Also you're catching an error from the host thread but the error you're throwing is on the second thread.
I fixed these issues, by waiting for the second thread to finish before checking the exception.
Anyways, the paradigmatic way to throw an exception across a thread can be found here: How can I propagate exceptions between threads?
#include <thread>
#include <iostream>
#include <stdexcept>
static std::exception_ptr _exceptionPtr = nullptr;
struct WorkerThread
{
std::thread thread;
void doSomething()
{
int seconds = 0;
bool shouldStop = false;
while (shouldStop == false)
{
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
std::cout << "time passed : " << ++seconds << "seconds" << std::endl;
if (seconds == 10) // something bad happened 10 seconds later
{
try
{
shouldStop = true;
throw std::runtime_error("something really bad happened");
}
catch (const std::runtime_error &ex)
{
_exceptionPtr = std::current_exception();
}
}
}
}
void run()
{
thread = std::thread([this] { doSomething(); });
//thread.detach();
}
};
int main(int argc, char *argv[])
{
WorkerThread workerThread;
workerThread.run();
workerThread.thread.join();
if (_exceptionPtr)
{
try
{
std::rethrow_exception(_exceptionPtr);
}
catch (std::runtime_error &ex)
{
// terminates program if exception happens
std::cout << "Program will now exit" << std::endl;
exit(EXIT_FAILURE); // but program never executes till here
}
}
for (;;)
{
// do A
// do B
// do C
// do ...
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
std::cout << "waiting for thread..." << std::endl;
}
return 0;
}

Exception should be caught at the for loop instead of workerThread.run(), since run() will exit immediately.
#include <thread>
#include <iostream>
#include <stdexcept>
static std::exception_ptr _exceptionPtr = nullptr;
struct WorkerThread
{
std::thread thread;
void doSomething()
{
int seconds = 0;
bool shouldStop = false;
while (shouldStop == false)
{
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
std::cout << "time passed : " << ++seconds << "seconds" << std::endl;
if (seconds == 10) // something bad happened 10 seconds later
{
try
{
shouldStop = true;
throw std::runtime_error("something really bad happened");
}
catch (const std::runtime_error &ex)
{
_exceptionPtr = std::current_exception();
}
}
}
}
void run()
{
thread = std::thread([this] { doSomething(); });
thread.detach();
}
};
int main(int argc, char *argv[])
{
WorkerThread workerThread;
workerThread.run();
for (;;)
{
// do A
// do B
// do C
// do ...
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
std::cout << "waiting for thread..." << std::endl;
if (_exceptionPtr)
{
try
{
std::rethrow_exception(_exceptionPtr);
}
catch (std::runtime_error &ex)
{
// terminates program if exception happens
std::cout << "Program will now exit" << std::endl;
exit(EXIT_FAILURE); // but program never executes till here
}
}
}
return 0;
}
Credits to #liliscent

Related

C++ Boost UDP receiver fails when put into thread

I have a UDP receiver that works. The code is here:
#include <array>
#include <iostream>
#include <string>
#include <boost/asio.hpp>
std::string getMyIp()
{
std::string result;
try
{
boost::asio::io_service netService;
boost::asio::ip::udp::resolver resolver(netService);
boost::asio::ip::udp::udp::resolver::query query(boost::asio::ip::udp::v4(), "google.com", "");
boost::asio::ip::udp::udp::resolver::iterator endpoints = resolver.resolve(query);
boost::asio::ip::udp::udp::endpoint ep = *endpoints;
boost::asio::ip::udp::udp::socket socket(netService);
socket.connect(ep);
boost::asio::ip::address addr = socket.local_endpoint().address();
result = addr.to_string();
//std::cout << "My IP according to google is: " << results << std::endl;
}
catch (std::exception& e)
{
std::cerr << "Could not deal with socket. Exception: " << e.what() << std::endl;
}
return result;
}
class receiver
{
private:
boost::asio::ip::udp::socket socket_;
boost::asio::ip::udp::endpoint sender_endpoint_;
std::array<char, 1024> data_;
public:
receiver(boost::asio::io_service& io_service,
const boost::asio::ip::address& listen_address,
const boost::asio::ip::address& multicast_address,
unsigned short multicast_port = 13000)
: socket_(io_service)
{
// Create the socket so that multiple may be bound to the same address.
boost::asio::ip::udp::endpoint listen_endpoint(listen_address, multicast_port);
socket_.open(listen_endpoint.protocol());
socket_.set_option(boost::asio::ip::udp::socket::reuse_address(true));
socket_.bind(listen_endpoint);
// Join the multicast group.
socket_.set_option(boost::asio::ip::multicast::join_group(multicast_address));
do_receive();
}
private:
void do_receive()
{
socket_.async_receive_from(boost::asio::buffer(data_), sender_endpoint_, [this](boost::system::error_code ec, std::size_t length)
{
if (!ec)
{
std::cout.write(data_.data(), length);
std::cout << std::endl;
do_receive();
}
});
}
};
int main(int argc, char* argv[])
{
try
{
boost::asio::io_service io_service;
receiver r(io_service, boost::asio::ip::make_address(getMyIp()), boost::asio::ip::make_address("224.0.0.0"), 13000);
io_service.run();
}
catch (std::exception& e)
{
std::cerr << "Exception: " << e.what() << "\n";
}
return 0;
}
I want to put the receiver code into a thread inside a class so I can do other things beside it:
#define _CRT_SECURE_NO_WARNINGS
#include <ctime>
#include <iostream>
#include <string>
#include <queue>
#include <boost/array.hpp>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/asio.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/thread.hpp>
#include <boost/thread/thread.hpp>
#include <boost/chrono.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
using boost::asio::ip::udp;
using std::cout;
using std::cin;
using std::endl;
using std::string;
using namespace std;
std::string getMyIp()
{
std::string result;
try
{
boost::asio::io_service netService;
boost::asio::ip::udp::resolver resolver(netService);
boost::asio::ip::udp::udp::resolver::query query(boost::asio::ip::udp::v4(), "google.com", "");
boost::asio::ip::udp::udp::resolver::iterator endpoints = resolver.resolve(query);
boost::asio::ip::udp::udp::endpoint ep = *endpoints;
boost::asio::ip::udp::udp::socket socket(netService);
socket.connect(ep);
boost::asio::ip::address addr = socket.local_endpoint().address();
result = addr.to_string();
//std::cout << "My IP according to google is: " << results << std::endl;
}
catch (std::exception& e)
{
std::cerr << "Could not deal with socket. Exception: " << e.what() << std::endl;
}
return result;
}
class UdpReceiver
{
private:
boost::asio::ip::udp::socket socket_;
boost::asio::ip::udp::endpoint sender_endpoint_;
std::array<char, 1024> data_;
string address_send, address_recv;
unsigned short port_send, port_recv;
boost::thread_group threads; // thread group
boost::thread* thread_main; // main thread
boost::thread* thread_receive; // receive thread
boost::thread* thread_send; // get/send thread
boost::mutex stopMutex;
bool initialize = false;
bool stop, showBroadcast;
int i_send, i_recv, i_operator,
interval_send, interval_recv, interval_operator,
mode;
string message_send, message_recv;
string message_STOP = "STOP";
public:
// constructor
UdpReceiver(boost::asio::io_service& io_service, std::string address, unsigned short port, int interval, int mode, bool show = false)
: socket_(io_service),
showBroadcast(show)
{
initialize = false;
Initialize(io_service, show);
}
UdpReceiver(boost::asio::io_service& io_service, bool show = false)
: socket_(io_service),
showBroadcast(show)
{
Initialize(io_service, show);
}
// destructor
~UdpReceiver()
{
// show exit message
cout << "Exiting UDP Core." << endl;
}
// initialize
void Initialize(boost::asio::io_service& io_service, bool show = false)
{
if (initialize == false)
{
GetMode(true);
GetInfo(true);
}
CreateEndpoint(io_service);
CreateThreads();
stop = false;
showBroadcast = show;
i_send = 0;
i_recv = 0;
i_operator = 0;
message_send.clear();
message_recv.clear();
initialize = true; // clear flag
}
void GetMode(bool default_value = false)
{
std::string input;
if (default_value)
{
mode = 0;
}
else
{
string prompt = "Set mode:\n0/other - Listen\n1 - Send\nEnter your choice: ";
cout << prompt;
getline(cin, input);
try
{
mode = stoi(input);
// set default mode to Listen
if (mode > 1)
mode = 0;
}
catch (exception ec)
{
cout << "Error converting mode: " << ec.what() << endl;
Stop();
}
}
}
void GetInfo(bool default_value = false)
{
// always called after GetMode()
string address;
unsigned short port;
int interval;
if (default_value)
{
address = getMyIp();
port = 13000;
interval = 500;
}
switch (mode)
{
case 0:
address_recv = address;
port_recv = port;
interval_recv = interval;
break;
case 1:
address_send = address;
port_send = port;
interval_send = interval;
break;
default:
// already set to 0 in GetMode()
break;
}
}
void CreateEndpoint(boost::asio::io_service& io_service)
{
// Create the socket so that multiple may be bound to the same address.
boost::asio::ip::udp::endpoint listen_endpoint(boost::asio::ip::address::from_string(address_recv), port_recv);
socket_.open(listen_endpoint.protocol());
socket_.set_option(boost::asio::ip::udp::socket::reuse_address(true));
socket_.bind(listen_endpoint);
// Join the multicast group.
socket_.set_option(boost::asio::ip::multicast::join_group(boost::asio::ip::address::from_string("224.0.0.0")));
}
void CreateThreads()
{
thread_main = new boost::thread(boost::ref(*this));
interval_operator = 500; // default value
switch (mode)
{
case 0:
thread_receive = new boost::thread(&UdpReceiver::Callable_Receive, this);
threads.add_thread(thread_receive);
break;
default:
// already set to 0 in GetMode()
break;
}
}
// start the threads
void Start()
{
// Wait till they are finished
threads.join_all();
}
// stop the threads
void Stop()
{
// warning message
cout << "Stopping all threads." << endl;
// signal the threads to stop (thread-safe)
stopMutex.lock();
stop = true;
stopMutex.unlock();
// wait for the threads to finish
thread_main->interrupt(); // in case not interrupted by operator()
threads.interrupt_all();
threads.join_all();
// close socket after everything closes
//socketPtr->close();
socket_.close();
}
void Callable_Receive()
{
while (!stop)
{
stopMutex.lock();
socket_.async_receive_from(boost::asio::buffer(data_), sender_endpoint_, [this](boost::system::error_code ec, std::size_t length)
{
if (!ec)
{
//cout << message_recv << endl;
std::cout.write(data_.data(), length);
std::cout << std::endl;
Callable_Receive();
}
});
stopMutex.unlock();
//cout << i_recv << endl;
++i_recv;
}
}
// Thread function
void operator () ()
{
while (!stop)
{
if (message_send == message_STOP)
{
try
{
this->Stop();
}
catch (exception e)
{
cout << e.what() << endl;
}
}
boost::this_thread::sleep(boost::posix_time::millisec(interval_operator));
boost::this_thread::interruption_point();
}
}
};
int main()
{
try
{
boost::asio::io_service io_service;
UdpReceiver mt(io_service, false);
mt.Start();
}
catch (std::exception& e)
{
std::cerr << "Exception: " << e.what() << "\n";
}
}
The async receive is inside Callable_Receive(), which is inside by thread_receive. I can see that thread running when the counter is printed on screen (which I comment out). However, the async_receive_from() never receives anything. Could someone tell me why this happens?
You have probably deadlock in Callable_Receive. In thread with Callable_Receive as body of thread you are calling stopMutex.lock before invoking async_receive_from function. async_receive_from returns immediately, but we don't know when lambda object passed as third paremeter to async_receive_from will be called. When body of lambda object is executed, you are calling Callable_Receive function, if stopMutex was locked (thread with Callable_Receive is still running and next iteration in while loop is being done) and you try to lock it again, you would get deadlock - on boost::mutex you cannot call lock method while mutex is already being locked by the same thread.
You should read about boost::recursive_mutex if you want to resolve this issue.

std::async and std::shared_future causes the program to fall

I am trying to run some function in asynchronous manner. For this purpose I wrote class called Core where I use std::async to run function in different thread and std::shared_future<int> to wait for this thread and possibly to get future result. This is code of test program:
#include <iostream>
#include <future>
class Core : public std::enable_shared_from_this<Core>
{
public:
Core()
: isRunning_(false) {
};
~Core() {
isRunning_ = false;
if (f_.valid())
{
f_.wait();
std::cout << "Result is: " << f_.get() << std::endl;
}
};
void Start() {
isRunning_ = true;
auto self(shared_from_this());
f_ = std::async(std::launch::async, [self, this]() {
try {
while (true) {
if (!isRunning_)
break;
std::cout << "Boom" << std::endl; // Error occurs here
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
catch (const std::exception& e) {
std::cerr << "Loop error:" << e.what();
}
return 999;
});
}
private:
std::shared_future<int> f_;
std::atomic<bool> isRunning_;
};
int main()
{
try {
std::shared_ptr<Core> load(new Core);
load->Start();
throw std::runtime_error("Generate error"); // Added in order to generate error
}
catch (const std::exception& e) {
std::cout << "Error occurred: " << e.what();
}
return 0;
}
Each time when I start this program it crashes at this line:
std::cout << "Boom" << std::endl; // Error occurs here
with this error:
That is debugger error and call stack which I managed to get during debugging:
Looks like Core destructor function doesn't call at all. Why is it happens? weird!!!
Could you tell me where is my mistake? Thanks.
When main thread returns from main() it starts tearing down the environment before terminating the whole process. All this while background thread is accessing objects there are being destroyed or have been destroyed already.
I am not sure what you are triying to achieve, but you are doing something wrong:
Your lambda should execute some work and return immediately after it is done e.g. you should never loop forever.
Your main thread should wait for your future to complete by calling std::future<T>::get().

std::future::get() does not catch the exception when the async function throws and program crashes

I am trying to call the future::get() function from the function started using the std::async function. In the async function I am throwing so that I can catch the exception in the future::get() call. However, I get an exception in the get() call that is not caught in the catch bloc and the program crashes with unhandeld exception. What am I missing ?
#include "stdafx.h"
#include <iostream>
#include <future>
void AsyncMethodThrowsExceptionTest();
void AsyncMethodThrowsException();
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
AsyncMethodThrowsExceptionTest();
return 0;
}
void AsyncMethodThrowsExceptionTest()
{
std::future<int> executionFuture;
try
{
executionFuture = async(launch::async, AsyncMethodThrowsException);
}
catch(...)
{
cout << "caught ex [1]";
}
std::future_status::future_status status;
status = executionFuture.wait_for(std::chrono::milliseconds(500u));
if(status == std::future_status::deferred)
{
cout << "AsyncMethodThrowsException has not started";
}
else if(status == std::future_status::timeout)
{
cout << "AsyncMethodThrowsException timed out";
}
else if(status == std::future_status::ready)
{
cout << "AsyncMethodThrowsException successfully completed";
try
{
if(executionFuture.valid())
{
executionFuture.get();
}
}
catch(const std::future_error& ex)
{
cout << "AsyncMethodThrowsExceptionTest catch block";
}
}
}
void AsyncMethodThrowsException()
{
throw(new exception("Exception from AsyncMethodThrowsException"));
}
Not only are you throwing a pointer to a std::exception in AsyncMethodThrowsException (there's no reason to do this), you're both catching a reference to an exception not a pointer, and a reference to a child class of std::exception at that; std::future::get() throws the exact exception thrown in the called function, not a std::future_error.
There are a couple of other syntax issues:
std::future<int> executionFuture should be std::future<void> executionFuture
std::future_status::future_status status should be std::future_status status.
std::exception does not have a constructor that takes a char const* or a std::string, this might be a compiler extension.
To sum things up:
#include <iostream>
#include <future>
void AsyncMethodThrowsExceptionTest();
void AsyncMethodThrowsException();
using namespace std;
int main()
{
AsyncMethodThrowsExceptionTest();
}
void AsyncMethodThrowsExceptionTest()
{
std::future<void> executionFuture;
try
{
executionFuture = async(launch::async, AsyncMethodThrowsException);
}
catch (...)
{
cout << "caught ex [1]";
}
std::future_status status = executionFuture.wait_for(std::chrono::milliseconds(500u));
if (status == std::future_status::deferred)
{
cout << "AsyncMethodThrowsException has not started";
}
else if (status == std::future_status::timeout)
{
cout << "AsyncMethodThrowsException timed out";
}
else if (status == std::future_status::ready)
{
cout << "AsyncMethodThrowsException successfully completed";
try
{
if(executionFuture.valid())
{
executionFuture.get();
}
}
catch(const std::exception& ex)
{
cout << "AsyncMethodThrowsExceptionTest catch block";
}
}
}
void AsyncMethodThrowsException()
{
throw runtime_error("Exception from AsyncMethodThrowsException");
}

Notification about exceptions in QtConcurrent::run

I know it doesn't make sense to actually handle an exception thrown in a different thread, but is there some way I can get notified that at least an exception occurred? E.g. something like
#include <QtConcurrentRun>
#include <iostream>
#include <stdexcept>
void MyFunction()
{
// std::cout << "MyFunction()" << std::endl;
throw std::runtime_error("Test exception.");
}
int main()
{
try
{
QtConcurrent::run(MyFunction);
}
catch(...)
{
std::cout << "Exception caught!" << std::endl;
}
}
exits quietly, even though an exception occurred. This is sometimes very confusing when the exception comes from deep down in the call stack somewhere.
------------EDIT-------------
I tried to write a wrapper like UmNyobe suggested, but I must be doing something wrong with the function pointers?
#include <QtConcurrentRun>
#include <QFutureWatcher>
#include <QObject>
#include <iostream>
#include <stdexcept>
void MyFunction()
{
// std::cout << "MyFunction()" << std::endl;
throw std::runtime_error("Test exception.");
}
template<typename TFirstParam, typename... TParams>
bool ExceptionWrapper(TFirstParam firstParam, TParams&& ...params)
{
// Here 'firstParam' should be a function pointer, and 'params' are the arguments
// that should be passed to the function
try
{
firstParam(params...);
}
catch(...)
{
std::cout << "Exception caught!" << std::endl;
return false; // failure
}
return true; // success
}
struct MyClass : public QObject
{
Q_OBJECT
MyClass()
{
connect(&this->FutureWatcher, SIGNAL(finished()), this, SLOT(slot_finished()));
}
void DoSomething()
{
void (*myFunctionPointer)() = MyFunction;
bool (*functionPointer)(decltype(myFunctionPointer)) = ExceptionWrapper;
QFuture<bool> future = QtConcurrent::run(functionPointer);
this->FutureWatcher.setFuture(future);
}
QFutureWatcher<void> FutureWatcher;
void slot_finished()
{
std::cout << "Finished" << std::endl;
if(!this->FutureWatcher.result())
{
std::cout << "There was an error!" << std::endl;
}
}
};
#include "ExceptionWrapper.moc"
int main()
{
MyClass myClass = new MyClass;
myClass->DoSomething();
}
The error I get is on this line:
QFuture<bool> future = QtConcurrent::run(functionPointer);
error: no matching function for call to 'run(bool (*&)(void (*)()))'
I know it doesn't make sense to actually handle an exception thrown in a different thread, but is there some way I can get notified that at least an exception occurred?
You can handle it by using the future returned from QtConcurrent::run. See this page for details. When you collect on the future, any unhandled exceptions will be rethrown. You can make a simple wrapper class to capture an exception and examine it in the receiving thread.
#include <QtGui>
#include <iostream>
#include <stdexcept>
class MyException : public QtConcurrent::Exception
{
public:
MyException(std::exception& err) : e(err) {}
void raise() const { throw *this; }
Exception* clone() const { return new MyException(*this); }
std::exception error() const { return e; }
private:
std::exception e;
};
// first concurrent function
int addFive(int n)
{
try
{
throw std::runtime_error("kablammo!");
//throw -1;
return n + 5;
}
catch (std::exception& e)
{
throw MyException(e);
}
}
// second concurrent function
void myVoidFunction()
{
try
{
throw std::runtime_error("oops!");
//throw -1;
}
catch (std::exception& e)
{
throw MyException(e);
}
}
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
QFuture<int> f1 = QtConcurrent::run(addFive, 50);
try
{
int r = f1.result();
std::cout << "result = " << r << std::endl;
}
catch (MyException& me)
{
std::cout << me.error().what() << std::endl;
}
catch (QtConcurrent::UnhandledException&)
{
std::cout << "unhandled exception in addFive\n";
}
QFuture<void> f2 = QtConcurrent::run(myVoidFunction);
try
{
// result() not available for QFuture<void>, use waitForFinished() to
// block until it's done.
f2.waitForFinished();
std::cout << "myVoidFunction finished\n";
}
catch (MyException& me)
{
std::cout << me.error().what() << std::endl;
}
catch (QtConcurrent::UnhandledException&)
{
std::cout << "unhandled exception in myVoidFunction\n";
}
QWidget w;
w.show();
return app.exec();
}
It seems that if an exception is thrown, the isCanceled() of an associated QFutureWatcher returns true:
#include <QApplication>
#include <QtConcurrentRun>
#include <QFutureWatcher>
#include <iostream>
#include <stdexcept>
void MyFunction()
{
std::cout << "MyFunction()" << std::endl;
throw std::runtime_error("Test exception.");
}
struct MyClass : public QObject
{
Q_OBJECT
public:
MyClass()
{
connect(&this->FutureWatcher, SIGNAL(finished()), this, SLOT(slot_finished()));
}
void DoSomething()
{
QFuture<void> future = QtConcurrent::run(MyFunction);
this->FutureWatcher.setFuture(future);
}
QFutureWatcher<void> FutureWatcher;
public slots:
void slot_finished()
{
std::cout << "Finished" << std::endl;
if(this->FutureWatcher.isCanceled())
{
std::cout << "There was an error!" << std::endl;
}
else
{
std::cout << "Success!" << std::endl;
}
}
};
#include "Exception.moc"
int main(int argc, char*argv[])
{
MyClass myClass;
myClass.DoSomething();
QApplication app(argc, argv);
return app.exec();
}
--------- Edit (Simplified version of Gordon Freeman's answer) ---------
The exceptions seem to be re-thrown even without using a QtConcurrent::Exception subclass?
#include <QtGui>
#include <iostream>
#include <stdexcept>
// non-void concurrent function
int addFive(int n)
{
throw std::runtime_error("addFive throw!");
return n+5;
}
// void concurrent function
void myVoidFunction()
{
throw std::runtime_error("myVoidFunction throw!");
}
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
QFuture<int> f1 = QtConcurrent::run(addFive, 50);
try
{
int r = f1.result();
std::cout << "result = " << r << std::endl;
}
catch (...)
{
std::cout << "exception in addFive." << std::endl;
}
QFuture<void> f2 = QtConcurrent::run(myVoidFunction);
try
{
// result() not available for QFuture<void>, use waitForFinished() to
// block until it's done.
f2.waitForFinished();
std::cout << "myVoidFunction finished\n";
}
catch (...)
{
std::cout << "exception in myVoidFunction\n";
}
QWidget w;
w.show();
return app.exec();
}
The good thing about QtConcurrent::run is that it accepts functions with a return value.
My two cents : catch the exception as early as possible...
disclaimer : I am really bad with exceptions in c++ :D
The code which is called in a different thread should return a value. In the case of a void function, or an existing function which doesn't catch exception you can define a wrapper (generic or not). For instance
int exceptionwrapper(){
int exception = 0;
try
{
myFunction();
}
catch(...){
exception = 1;
std::cout << "Exception caught!" << std::endl;
}
return exception;
}
Then later
QFuture<int> future = QtConcurrent::run(exemptionwrapper);
futurewatcher.setFuture(future);
You just use the future watcher to be able to examine the future later, when the function is over.

boost disable_interruption not preventing thread_interrupted

I am trying to prevent interruption of a thread while it is in a particular scope. However, using boost::this_thread::disable_interruption di() does not seem to have any effect.
#include <boost/thread.hpp>
#include <iostream>
void worker() {
std::cout << "START" << std::endl;
for(;;) {
{
boost::this_thread::disable_interruption di();
try {
boost::this_thread::sleep(boost::posix_time::seconds(1));
}
catch(boost::thread_interrupted & e) {
assert( false );
}
}
try {
boost::this_thread::interruption_point();
}
catch(boost::thread_interrupted & e) {
break;
}
}
std::cout << "END" << std::endl;
}
int main() {
boost::thread thread(&worker);
thread.interrupt();
thread.join();
}
The documentation appears to imply that boost::this_thread::sleep() will not throw boost::thread_interrupted while di is in scope.
What am I doing wrong?
You should remove parenthesis in the following line:
//boost::this_thread::disable_interruption di();
boost::this_thread::disable_interruption di;
Instead of creating disable_interruption object, you declared function di.