Subject: [Boost-bugs] [Boost C++ Libraries] #9535: Missing exception safety might result in crash
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2013-12-30 11:06:56
#9535: Missing exception safety might result in crash
------------------------------+----------------------
Reporter: anonymous | Owner: anthonyw
Type: Bugs | Status: new
Milestone: To Be Determined | Component: thread
Version: Boost 1.55.0 | Severity: Problem
Keywords: |
------------------------------+----------------------
As I was curious as to how boost::wait_for_any is implemented, and I think
I found a little flaw in the future_waiter class in
boost/thread/future.hpp ( which the documentation incorrectly lists as
<boost/thread/futures.hpp> ):
The future_waiter class registers it's condition variable in the add
function
{{{
template<typename F>
void add(F& f)
{
if(f.future_)
{
futures.push_back(registered_waiter(f.future_,f.future_->register_external_waiter(cv),future_count));
}
++future_count;
}
}}}
and unregisters it in the destructor
{{{
~future_waiter()
{
for(count_type i=0;i<futures.size();++i)
{
futures[i].future_->remove_external_waiter(futures[i].wait_iterator);
}
}
}}}
However, if the program encounters an out-of-memory condition during it's
call to push_back in add(), the registered_waiter is not stored in the
vector und thus is not unregistered in the destructor, so as soon as the
future readies up, it calls notify_all on a dangling pointer, resulting in
a crash. I was able to successfully construct this scenario by overloading
operator new() using GCC on a unix-like OS.
I suggest adding a mechanism to unregister the waiter in case of an
exception. Changing the add function to the following fixed it for me:
{{{
template<typename F>
void add(F& f)
{
if(f.future_)
{
registered_waiter
waiter(f.future_,f.future_->register_external_waiter(cv),future_count);
try {
futures.push_back(waiter);
} catch(...)
{f.future_->remove_external_waiter(waiter.wait_iterator); throw;}
}
++future_count;
}
}}}
As you see, I have just introduced a local variable and a try-catch block.
There could be more elegant solutions, but this was the first one that
came to mind.
-- Ticket URL: <https://svn.boost.org/trac/boost/ticket/9535> Boost C++ Libraries <http://www.boost.org/> Boost provides free peer-reviewed portable C++ source libraries.
This archive was generated by hypermail 2.1.7 : 2017-02-16 18:50:15 UTC