-
Notifications
You must be signed in to change notification settings - Fork 425
Description
cpp-netlib calls boost::promise::set_exception()
with a std::exception_ptr
as argument in a number of places (for example, in http_async_connection::handle_received_data()
.
boost::promise::set_exception()
has two overloads:
void set_exception(boost::exception_ptr e);
template <typename E>
void set_exception(E e);
The first overload takes a boost::exception_ptr
(note: not std::exception_ptr
) wrapping a concrete exception. The second overload accepts a concrete exception object itself (and internally wraps it in boost::exception_ptr
).
When set_exception()
is called with an argument of type std::exception_ptr
, the second overload is matched, so boost::promise
treats std::exception_ptr
as the concrete exception type.
The reason this is a problem (besides the inefficiency of wrapping an exception in two layers of exception pointers), is that when the other side (future::get()
) throws the exception, the thrown exception object will be the std::exception_ptr
itself, not the concrete exception object that it wraps.
For example, suppose the concrete exception type is boost::system::system_error
(as is the case in http_async_connection::handle_received_data()
). While the client code may be expecting to catch it with a catch clause like this:
catch (boost::system::system_error& e) {
...
}
in fact this catch clause will not be matched, because the thrown type was std::exception_ptr
.
The fix is simple: when calling boost::promise::set_exception()
, don't wrap the concrete exception type with std::make_exception_ptr
: just pass the concrete exception object directly.