[Boost-users] [Thread] program crashes from time to time when deleting unique_future<void>

83 views
Skip to first unread message

Soderback, Johan

unread,
Nov 21, 2011, 11:40:04 AM11/21/11
to boost...@lists.boost.org

Hi,

 

I have a small example program that crashes from time to time.

I would appreciate some help to understand why.

 

In function run() executed on the main thread I create a packaged_task (pt), put it in a queue (_q) and wait for it to get executed (fu.get()).

In another thread the tasks are executed when the queue _q is populated.

The task I'm running always throws/rethrows intentionally.

 

It results (from time to time) in an access violation when the unique_future, fu, is deleted.

See the stack trace at the bottom.

 

Anybody see any flaws in this design?

 

I have tried 1.47.0 and 1.48.0,  MSVC 2005.

 

Here's the code.

 

*****************************************************

 

#include <boost/exception/all.hpp>

#include <boost/thread.hpp>

#include <sstream>

#include <iostream>

 

 

struct Exception

  : public virtual std::exception

  , public virtual boost::exception

{

};

 

struct TheException  : public virtual Exception {};

 

void throwf()

{

  try

  {

    BOOST_THROW_EXCEPTION(TheException());

  }

  catch (...)

  {

    boost::current_exception_diagnostic_information();

    throw;

  }

}

 

struct Test

{

  Test()

  {

    _t.reset(new boost::thread(boost::bind(&Test::executor, this)));

  }

 

  ~Test()

  {

    _t->join();

  }

 

  void executor()

  {

    for (;;)

    {

      boost::unique_lock<boost::mutex> lk(_mx);

 

      while(_q.empty())

      {

        _cv.wait(lk);

      }

 

      boost::shared_ptr< boost::packaged_task<void> > pt = _q.front();

      _q.pop_front();

      lk.unlock();

 

      (*pt)();

    }

  }

 

  void run()

  {

    for (;;)

    {

      const int N = 20000;   

      for (int j = 0; j < N; ++j)

      {

        boost::shared_ptr< boost::packaged_task<void> > pt(new boost::packaged_task<void>(throwf));

        boost::unique_future<void> fu = pt->get_future();

       

        {

          boost::unique_lock<boost::mutex> lk(_mx);

          _q.push_back(pt);

          pt.reset();

        }

      

        _cv.notify_one();

 

        try

        {

          fu.get();

          assert(false);

        }

        catch (const TheException& )

        {

        }

        catch (const boost::exception& )

        {

          assert(false);

        }

        catch (...) {

          assert(false);

        }

      }

      std::cout << ".";

    }

  }

 

private:

  boost::mutex _mx;

  std::list< boost::shared_ptr< boost::packaged_task<void> > > _q;

  boost::shared_ptr<boost::thread> _t;

  boost::condition_variable_any _cv;

};

 

 

int main(int, char*)

{

  Test test;

  test.run();

}

 

*****************************************************

 

Here is the callstack, program terminated with access violation.

 

Unhandled exception at 0x0043196b in crasher.exe: 0xC0000005: Access violation reading location 0xdddddded.

 

>                 crasher.exe!boost::exception_detail::refcount_ptr<boost::exception_detail::error_info_container>::release()  Line 78 + 0x18 bytes       C++

                  crasher.exe!boost::exception_detail::refcount_ptr<boost::exception_detail::error_info_container>::~refcount_ptr<boost::exception_detail::error_info_container>()  Line 35        C++

                 crasher.exe!boost::exception::~exception()  Line 278 + 0xb bytes                C++

                 crasher.exe!boost::exception_detail::clone_impl<TheException>::`vbase destructor'()  + 0x41 bytes          C++

                 crasher.exe!boost::exception_detail::clone_impl<TheException>::`scalar deleting destructor'()  + 0x2b bytes   C++

                 crasher.exe!boost::checked_delete<boost::exception_detail::clone_base const >(const boost::exception_detail::clone_base * x=0x006f7d10)  Line 34 + 0x35 bytes  C++

                 crasher.exe!boost::detail::sp_counted_impl_p<boost::exception_detail::clone_base const >::dispose()  Line 78 + 0xc bytes       C++

                 crasher.exe!boost::detail::sp_counted_base::release()  Line 102 + 0xf bytes  C++

                 crasher.exe!boost::detail::shared_count::~shared_count()  Line 309             C++

                 crasher.exe!boost::shared_ptr<boost::exception_detail::clone_base const >::~shared_ptr<boost::exception_detail::clone_base const >()  + 0x2e bytes                 C++

                 crasher.exe!boost::exception_ptr::~exception_ptr()  + 0x2b bytes               C++

                 crasher.exe!boost::detail::future_object_base::~future_object_base()  Line 106 + 0x9c bytes                 C++

                 crasher.exe!boost::detail::future_object<void>::~future_object<void>()  + 0x2b bytes    C++

                 crasher.exe!boost::detail::task_base<void>::~task_base<void>()  + 0x2b bytes             C++

                 crasher.exe!boost::detail::task_object<void,void (__cdecl*)(void)>::~task_object<void,void (__cdecl*)(void)>()  + 0x2b bytes      C++

                 crasher.exe!boost::detail::task_object<void,void (__cdecl*)(void)>::`scalar deleting destructor'()  + 0x2b bytes                 C++

                 crasher.exe!boost::checked_delete<boost::detail::task_object<void,void (__cdecl*)(void)> >(boost::detail::task_object<void,void (__cdecl*)(void)> * x=0x006f7b10)  Line 34 + 0x34 bytes        C++

                 crasher.exe!boost::detail::sp_counted_impl_p<boost::detail::task_object<void,void (__cdecl*)(void)> >::dispose()  Line 78 + 0xc bytes                 C++

                 crasher.exe!boost::detail::sp_counted_base::release()  Line 102 + 0xf bytes  C++

                 crasher.exe!boost::detail::shared_count::~shared_count()  Line 309             C++

                 crasher.exe!boost::shared_ptr<boost::detail::future_object<void> >::~shared_ptr<boost::detail::future_object<void> >()  + 0x2e bytes         C++

                 crasher.exe!boost::unique_future<void>::~unique_future<void>()  Line 644 + 0x2b bytes                 C++

                 crasher.exe!Test::run()  Line 95 + 0xc bytes          C++

                 crasher.exe!main(int __formal=1, int __formal=1)  Line 112      C++

                 crasher.exe!__tmainCRTStartup()  Line 597 + 0x19 bytes          C

                 crasher.exe!mainCRTStartup()  Line 414                C

                 kernel32.dll!7c817067()   

                 [Frames below may be incorrect and/or missing, no symbols loaded for kernel32.dll]        

 

 

 

 

 

 

 



Please consider the environment before printing this e-mail.

The contents of this e-mail message (including any attachments) are confidential to and are intended to be conveyed for the use of the recipient to whom it is addressed only. If you receive this transmission in error, please notify the sender of this immediately and delete the message from your system. Any distribution, reproduction or use of this message by someone other than recipient is not authorized and may be unlawful.

Alex Perry

unread,
Nov 21, 2011, 3:33:51 PM11/21/11
to Johan.S...@elekta.com, boost...@lists.boost.org

On Mon, 21 Nov 2011 16:40:04 +0000 "Soderback, Johan" <Johan.S...@elekta.com> wrote :-


> Hi,
>
> I have a small example program that crashes from time to time.
> I would appreciate some help to understand why.
>
> In function run() executed on the main thread I create a packaged_task (pt),
> put it in a queue (_q) and wait for it to get executed (fu.get()).
> In another thread the tasks are executed when the queue _q is populated.
> The task I'm running always throws/rethrows intentionally.
>
> It results (from time to time) in an access violation when the unique_future,
> fu, is deleted.
> See the stack trace at the bottom.
>
> Anybody see any flaws in this design?
>
> I have tried 1.47.0 and 1.48.0, MSVC 2005.
>

Trying your example on vs2010 it crashes continuously - changing your throwf() function to the following appears to sort it - not quite sure why a simple throw fails though - or whether this was your problem under vs2005

void throwf()
{
try
{
BOOST_THROW_EXCEPTION(TheException());
}
catch (boost::exception const & )
{
boost::rethrow_exception( boost::current_exception() );
}
}

HTH

Alex
_______________________________________________
Boost-users mailing list
Boost...@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/boost-users

Soderback, Johan

unread,
Nov 22, 2011, 12:01:49 PM11/22/11
to boost...@lists.boost.org, Alex....@smartlogic.com
Thanx Alex,

It works but not when I have the boost::current_exception_diagnostic_information() call
in the throwf() as in my example.

void throwf()
{
try
{
BOOST_THROW_EXCEPTION(TheException());
}
catch (...)
{
boost::current_exception_diagnostic_information();
boost::rethrow_exception( boost::current_exception() ); // or just throw;
}
}

The plain throw version seems to work as well without it, the call certainly triggers something.
Anyway, any idea what could be wrong?

/Johan

HTH

Alex

Please consider the environment before printing this e-mail.

The contents of this e-mail message (including any attachments) are confidential to and are intended to be conveyed for the use of the recipient to whom it is addressed only. If you receive this transmission in error, please notify the sender of this immediately and delete the message from your system. Any distribution, reproduction or use of this message by someone other than recipient is not authorized and may be unlawful.

Emil Dotchevski

unread,
Nov 22, 2011, 2:16:12 PM11/22/11
to boost...@lists.boost.org, Alex....@smartlogic.com
On Tue, Nov 22, 2011 at 9:01 AM, Soderback, Johan
<Johan.S...@elekta.com> wrote:
> Thanx Alex,
>
> It works but not when I have the boost::current_exception_diagnostic_information() call
> in the throwf() as in my example.
>
> void throwf()
> {
>  try
>  {
>    BOOST_THROW_EXCEPTION(TheException());
>  }
>  catch (...)
>  {
>    boost::current_exception_diagnostic_information();
>    boost::rethrow_exception( boost::current_exception() ); // or just throw;
>  }
> }
>
> The plain throw version seems to work as well without it, the call  certainly triggers something.
> Anyway, any idea what could be wrong?
>
> /Johan

Seems suspicious, probably a bug in boost::exception_ptr. I'll look
into it as time permits.

Emil Dotchevski
Reverge Studios, Inc.
http://www.revergestudios.com/reblog/index.php?n=ReCode

Emil Dotchevski

unread,
Nov 23, 2011, 3:56:41 AM11/23/11
to boost...@lists.boost.org
On Mon, Nov 21, 2011 at 8:40 AM, Soderback, Johan
<Johan.S...@elekta.com> wrote:
> Hi,
>
> I have a small example program that crashes from time to time.
>
> I would appreciate some help to understand why.

Your program ended up with a copy of an exception object, which shared
internal state with the original, but the original and the copy were
in different threads. There is special machinery in Boost Exception
which should have prevented that situation.

There was a bug in that system. I think it's fixed now, see trunk
revision number 75636.

Soderback, Johan

unread,
Nov 24, 2011, 10:23:04 AM11/24/11
to boost...@lists.boost.org
> -----Original Message-----
> From: boost-use...@lists.boost.org [mailto:boost-users-
> bou...@lists.boost.org] On Behalf Of Emil Dotchevski
> Sent: den 23 november 2011 09:57
>
> There was a bug in that system. I think it's fixed now, see trunk
> revision number 75636.
>

Hi Emil,
Yes it solves it, thanks for fixing the problem so quickly!

/Johan

Please consider the environment before printing this e-mail.

The contents of this e-mail message (including any attachments) are confidential to and are intended to be conveyed for the use of the recipient to whom it is addressed only. If you receive this transmission in error, please notify the sender of this immediately and delete the message from your system. Any distribution, reproduction or use of this message by someone other than recipient is not authorized and may be unlawful.

Reply all
Reply to author
Forward
0 new messages