- Notifications
You must be signed in to change notification settings - Fork425
Description
cpp-netlib callsboost::promise::set_exception()
with astd::exception_ptr
as argument in a number of places (for example, inhttp_async_connection::handle_received_data()
.
boost::promise::set_exception()
has two overloads:
voidset_exception(boost::exception_ptr e);template<typename E>voidset_exception(E e);
The first overload takes aboost::exception_ptr
(note:notstd::exception_ptr
) wrapping a concrete exception. The second overload accepts a concrete exception object itself (and internally wraps it inboost::exception_ptr
).
Whenset_exception()
is called with an argument of typestd::exception_ptr
, the second overload is matched, soboost::promise
treatsstd::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 thestd::exception_ptr
itself, not the concrete exception object that it wraps.
For example, suppose the concrete exception type isboost::system::system_error
(as is the case inhttp_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 wasstd::exception_ptr
.
The fix is simple: when callingboost::promise::set_exception()
, don't wrap the concrete exception type withstd::make_exception_ptr
: just pass the concrete exception object directly.