Throwing Clear Exception in a Multithreaded Context with a proram STOP - c++

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

Related

Why `std::invalid_argument` is not caught with no-rtti in macOS M1 environment?

Today I met a weird behaviour in catching exceptions in C++, could anyone clarify it to me? Code snippe
#include <iostream>
#include <string>
#include <exception>
int main() {
try {
std::stod("notanumber");
} catch (const std::invalid_argument&) {
std::cerr << "std::invalid_argument" << std::endl;
} catch (const std::out_of_range&) {
std::cerr << "std::out_of_range" << std::endl;
} catch (const std::exception&) {
std::cerr << "Caught by ancestor" << std::endl;
} catch (...) {
auto ptr = std::current_exception();
auto type = __cxxabiv1::__cxa_current_exception_type();
std::cerr << type->name() << std::endl;
std::cerr << "..." << std::endl;
}
return 0;
}
Writes to output
St16invalid_argument
...
Environment details
C++ 14, disabled RTTI
Clang 13.1.6 arm64-apple-darwin-21.6.0
macOS Monterey 12.6
I expect exception to be caught on the very first catch block
Upd. Even simplest catch doesn't work for me on the environment
try {
std::stod("notanumber");
} catch (const std::invalid_argument&) { // not caught
std::cerr << "std::invalid_argument" << std::endl;
}

VC++ std::current_exception returns null in uncaught exception

It seems that the default terminate handler in Windows does not print the ex.what() of the exception that caused it.
As a workaround I thought to implement a custom terminate handler to print the exception:
#include <iostream>
void term_func()
{
std::cout << "term_func was called by terminate.(1)" << std::endl;
std::exception_ptr eptr = std::current_exception();
try
{
if(eptr)
{
std::rethrow_exception(eptr);
}
}
catch(const std::exception& e)
{
std::cout << "Caught exception \"" << e.what() << "\"\n";
}
std::cout << "term_func was called by terminate.(2)" << std::endl;
exit(-1);
}
int main(int argc, char **argv)
{
std::set_terminate(term_func);
throw std::runtime_error("is windows broken?");
}
This works well in GCC and Clang++ (prints also the content of the exception), however in VC++ it only prints:
term_func was called by terminate.(1)
term_func was called by terminate.(2)
Now, are there any workarounds to this? Or to the initial problem?

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

Why does boost's managed_mapped_file :: shrink_to_fit behave differently on Windows and Linux?

This is about C ++ library boost.
The managed_mapped_file :: shrink_to_fit function works differently on Linux and Windows.
On Linux, this function succeeds even if the target instance exists.
However, on Windows, this function will fail if the target instance exists.
Is this correct behavior?
It seems correct to do the same behavior, is this a bug?
I put the sample code below.
Compilation environment
boost:version.1.65.1
Windows
VisualStudio2017
WSL(Ubuntu16.04)
Linux
UbuntuServer17.10,
Clang++5.0,
g++7.2.0
Compile with
clang++-5.0 -std=c++1z ./test.cpp -o test -lpthread
#define BOOST_DATE_TIME_NO_LIB
#include <boost/interprocess/managed_mapped_file.hpp>
#include <boost/interprocess/file_mapping.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <vector>
#include <iostream>
namespace bip = boost::interprocess;
using intAlloc = bip::allocator<int, bip::managed_mapped_file::segment_manager>;
using intVec = std::vector<int, intAlloc>;
int main() {
bip::managed_mapped_file *p_file_vec;
intVec *vecObj;
std::string fileName = "tmp.dat";
size_t fileSize = 1024 * 1024 * 1;
bip::file_mapping::remove(fileName.c_str());
p_file_vec = new bip::managed_mapped_file(bip::create_only, fileName.c_str(), fileSize);
vecObj = p_file_vec->construct<intVec>("myVecName")(p_file_vec->get_allocator<int>());
for (size_t i = 0; i < 10; i++)
{
vecObj->push_back(1 + 100);
}
p_file_vec->flush();
try
{ //Fail when execute on Windows(WSL),but Success on Linux(Ubuntu17.10).
std::cout << "try to shrink:pointer has existed yet!" << std::endl;
bip::managed_mapped_file::shrink_to_fit(fileName.c_str());
std::cout << "success to shrink!" << std::endl;
}
catch (const boost::interprocess::interprocess_exception &ex)
{
std::cerr << "fail to shrink!" << std::endl;
std::cerr << ex.what() << std::endl;;
}
std::cout <<"please pless enter key."<< std::endl;
std::cin.get();
try
{ //Success when execute on Windows(WSL) and Linux(Ubuntu17.10).
delete p_file_vec;
std::cout << "try to shrink:pointer has deleted!" << std::endl;
bip::managed_mapped_file::shrink_to_fit(fileName.c_str());
std::cout << "success to shrink!" << std::endl;
}
catch (const std::exception& ex)
{
std::cerr << "fail to shrink!" << std::endl;
std::cerr << ex.what() << std::endl;;
}
std::cout << "please pless enter key." << std::endl;
std::cin.get();
}
Don't use new and delete in C++ (rule of thumb).
Apart from that
delete p_file_vec;
does NOT delete anything physical. It effectively disconnects from the mapped file. This is also why shrink_to_fit works: the documentation explicitly says:
If the application can find a moment where no process is attached it can grow or shrink to fit the managed segment.
And here
So, in short: the behaviour is correct on both platforms. It's just UNDEFINED what happens in your case when you shrink while the mapped file is in use (on Ubuntu).
Fixed Code:
Live On Coliru
#include <boost/interprocess/managed_mapped_file.hpp>
#include <iostream>
#include <vector>
namespace bip = boost::interprocess;
using intAlloc = bip::allocator<int, bip::managed_mapped_file::segment_manager>;
using intVec = std::vector<int, intAlloc>;
int main() {
std::string const fileName = "tmp.dat";
bip::file_mapping::remove(fileName.c_str());
{
bip::managed_mapped_file file_vec(bip::create_only, fileName.c_str(), 1l << 20);
auto *vecObj = file_vec.construct<intVec>("myVecName")(file_vec.get_allocator<int>());
for (size_t i = 0; i < 10; i++) {
vecObj->push_back(1 + 100);
}
}
try { // Success when execute on Windows(WSL) and Linux(Ubuntu17.10).
std::cout << "try to shrink:pointer has deleted!" << std::endl;
bip::managed_mapped_file::shrink_to_fit(fileName.c_str());
std::cout << "success to shrink!" << std::endl;
} catch (const std::exception &ex) {
std::cerr << "fail to shrink!" << std::endl;
std::cerr << ex.what() << std::endl;
;
}
}

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.