Boost version: 1.61, GCC version 6.2.0, C++14
Exceptions inside a boost::async()
call seem to lose their type, while it works correctly with std::async
. Is there a fundamental difference between std::async
and boost::async
I'm missing?
The following code works (using std::async
):
#include <iostream>
#include <stdexcept>
#include <future>
using namespace std;
struct MyException : std::exception {
const char* what() const noexcept override { return "message"; }
};
int main() {
try {
auto future = std::async(std::launch::async, [] { throw MyException(); });
future.get();
} catch (const MyException& e) {
cout << "MyException caught. Message: " << e.what() << endl;
} catch (const std::exception& e) {
cout << "std::exception caught. Message: " << e.what() << endl;
}
}
and outputs
$ g++ test.cpp -std=c++14 -lpthread -lboost_thread -lboost_system && ./a.out
MyException caught. Message: message
However, the following code (it's the same, just using boost::async
instead of std::async
) does not work as expected:
#include <iostream>
#include <stdexcept>
#include <boost/thread/future.hpp>
using namespace std;
struct MyException : std::exception {
const char* what() const noexcept override { return "message"; }
};
int main() {
try {
auto future = boost::async(boost::launch::async, [] { throw MyException(); });
future.get();
} catch (const MyException& e) {
cout << "MyException caught. Message: " << e.what() << endl;
} catch (const std::exception& e) {
cout << "std::exception caught. Message: " << e.what() << endl;
}
}
It outputs:
$ g++ test.cpp -std=c++14 -lpthread -lboost_thread -lboost_system && ./a.out
std::exception caught. Message: std::exception
It also doesn't work for boost::future::then
continuations:
#include <iostream>
#include <stdexcept>
#define BOOST_THREAD_VERSION 4
#include <boost/thread/future.hpp>
using namespace std;
struct MyException : std::exception {
const char* what() const noexcept override { return "message"; }
};
int main() {
try {
auto future = boost::make_ready_future(3).then([](boost::future<int>) -> int { throw MyException(); });
future.get();
} catch (const MyException& e) {
cout << "MyException caught. Message: " << e.what() << endl;
} catch (const std::exception& e) {
cout << "std::exception caught. Message: " << e.what() << endl;
}
}
outputs:
$ g++ test.cpp -std=c++14 -lpthread -lboost_thread -lboost_system && ./a.out
std::exception caught. Message: std::exception
So the concrete type of the exception seems to be lost when crossing the thread boundary. However, it doesn't seem to be connected to threading, because according to my tests, the same is true for std::launch::deferred
(which works fine) and boost::launch::deferred
(which loses the exception type).