Notification about exceptions in QtConcurrent::run - c++

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.

Related

Throwing Clear Exception in a Multithreaded Context with a proram STOP

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?
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 MSVC uses per-thread handlers, and for it to work you need to call set_termnate() in every thread separatelly.
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;
}
}

Exit program when catch exception from thread

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

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");
}

Catch a throw exception with a custom string parameter

I'm trying to implement something similar to the following in my VS 2008 C++/MFC project:
class myClass()
{
public:
myClass()
{
//Do work... check for errors
if(var < 0)
{
//Error
TCHAR buff[1024];
_snwprintf_s(buff, SIZEOF(buff), L"ERROR: The value of var=%d", var);
throw buff;
}
}
};
__try
{
//Begin using class above
//The class member may be also defined on the global scale, thus
//the following exception trap may happen via SetUnhandledExceptionFilter
myClass mc;
}
__except(1)
{
//Process unhandled exception
//But how to trap the string passed in 'throw' above?
}
But I can't seem to catch the "string" that I'm passing in the throw statement.
Use std::runtime_error, eg:
#include <stdexcept>
class myClass()
{
public:
myClass()
{
//Do work...check for errors
if(var < 0)
{
//Error
char buff[1024];
_snprintf_s(buff, SIZEOF(buff), "ERROR: The value of var=%d", var);
throw std::runtime_error(buff);
}
}
};
try
{
//Begin using class above
myClass mc;
}
catch (const std::runtime_error &e)
{
//Process unhandled exception
//e.what() will return the string message ...
}
You can try something like this, for example:
struct CustomError {
CustomError(std::string& info)
: m_info(info) {}
std::string m_info;
};
/*...*/
int main() {
try {
std::string info = "yo dawg";
throw CustomError(info);
}
catch (CustomError& err) {
std::cout << "Error:" << err.m_info;
}
}
Character buffer way:
#include <string>
#include <iostream>
void DoSomething()
{
throw "An error occurred!";
}
int main()
{
try
{
DoSomething();
std::cout << "Nothing bad happened" << std:endl;
}
catch(const char &err)
{
std::cerr << err << std::endl;
}
}
, or std::string way:
#include <string>
#include <iostream>
void DoSomething()
{
throw std::string("An error occurred!");
}
int main()
{
try
{
DoSomething();
std::cout << "Nothing bad happened" << std:endl;
}
catch(std::string &err)
{
std::cerr << err << std::endl;
}
}