Boost logo

Boost Users :

Subject: Re: [Boost-users] Unable to catch exception using boost::asio
From: Alex Black (alex_at_[hidden])
Date: 2009-07-15 14:31:16


>
> > >> Message: 3
> > >> Date: Wed, 15 Jul 2009 10:56:22 -0500
> > >> From: Zachary Turner <divisortheory_at_[hidden]>
> > >> Subject: Re: [Boost-users] Unable to catch exception using
> > >> boost::asio
> > >> To: boost-users_at_[hidden]
> > >> Message-ID:
> > >>      
> <478231340907150856x12c9fd92w3b06630d349eef36_at_[hidden]>
> > >> Content-Type: text/plain; charset=ISO-8859-1
> > >>
> > >> > I wrapped my call to run() in a try-catch, no luck, no
> exception
> > >> > appears to be being thrown by io_service.run().
> > >> >
> > >> > void CBaseWebServer::RunIoService() { ? ? ? ?try ? ? ?
> > ?{ ? ? ? ? ?
> > >> > ? ? ?m_IoService.run(); ? ? ? ?} ? ? ? ?catch ( ... ) ?
> > ? ? ?{ ? ?
> > >> > ? ? ? ? ? ?cout << "Unhandled exception in
> > >> RunIoService"; ? ? ? ?}
> > >> > } _______________________________________________
> > >> > Boost-users mailing list
> > >> > Boost-users_at_[hidden]
> > >> > http://lists.boost.org/mailman/listinfo.cgi/boost-users
> > >> >
> > >>
> > >>
> > >> That probably won't help.  Notice that
> > >> CBaseWebServer::RunIoService() is not in the call stack at
> > the point
> > >> you're seeing the exception.
> > >> After looking at your callstack again, I believe you're
> > throwing from
> > >> a destructor.  In particular, notice in your callstack
> > that you have
> > >> this:
> > >>
> > >> 26 ~ProtoBufStreamAdaptor() /home/noirs/workspace/myfile2.cpp:10
> > >> 0x000000000042c6e5
> > >> 25 CWebServer::HandleGetNeighbors()
> > >> /home/noirs/workspace/myfile3.cpp:215 0x000000000041d2d8
> > >>
> > >>
> > >> These appear to both be in your own code.  My suspicion
> is that an
> > >> exception occurs in CWebServer::HandleGetNeighbors(),
> > which causes it
> > >> to unwind the stack and execute destructors.
> > >> In particular a destructor for an object of type
> > >> ProtoBufStreamAdaptor() is called, and this destructor
> then throws
> > >> another exception.  At this point your program will definitely
> > >> terminate immediately.
> > >>
> > >> First check the destructor of ProtoBufStreamAdaptor() to
> > see why it's
> > >> throwing (destructors should _never_ throw under any
> > circumstances),
> > >> and then check the code of
> > >> CWebServer::HandleGetNeighbors() to find the original error.
> > >
> > > Thanks for continuing to help with this.
> > >
> > > I had the same thoughts as you, and I've looked into that
> > with no luck.
> > > For example, here is the code for ~ProtoBufStreamAdaptor():
> > >
> > > ProtoBufStreamAdaptor::~ProtoBufStreamAdaptor(void)
> > > {}
> > >
> > > The original error is related to the client (on the other
> end of the
> > > socket) being interrupted.  Presumably some socket operation is
> > > throwing an exception, e.g. I'm writing to the socket after
> > the client
> > > has disconnected.
> > >
> > > You mentioned never throwing exceptions in destructors -
> > sounds like
> > > good advice, thx. Two points though:
> > > 1. If an exception is thrown in a destructor can it not be
> > caught with
> > > a try catch( ... )?
> > > 2. I'll look over the code more closely and see if there are any
> > > destructors throwing.
> >
> > Since it looks like the callstack is perfectly fine up
> until something
> > that happens in HandleGetNeighbors(), perhaps you could put a
> > breakpoint at the very first line of
> > HandleGetNeighbors() and single step until something bad
> happens. I'm
> > not familiar with your code enough to be able to say for sure, but
> > just because ProtoBufStreamAdaptor's destructor is empty
> doesn't mean
> > it's not throwing. Does it contain members that are also
> structures,
> > whose destructors might throw? For example:
> >
> > struct ProtoBufStreamAdaptor
> > {
> > ~ProtoBufStreamAdaptor() {}
> > shared_ptr<blah> blah_;
> > };
> >
> >
> > Now even though this has an empty destructor, if it turns out that
> > blah_ is actually the last shared reference to the
> instance, it will
> > invoke blah::~blah(). This can't throw either.
> >
> > Some debuggers provide mechanisms so that you can stop at the exact
> > point an exception is thrown, rather than where it is handled. You
> > might try that as well. If your debugger doesn't support this
> > natively, then you might be able to achieve the same thing
> by noting
> > that the exception claims to be of type
> > 'boost::exception_detail::clone_impl<boost::exception_detail::
> > error_info_injector<boost::system::system_error>'.
> > So put a breakpoint inside the constructor of
> > boost::exception_detail::clone_impl and presumably your breakpoint
> > should get hit at the moment the exception is thrown, and
> you'll have
> > a callstack of the offending code.
>
> Good call. Yes, ProtoBufStreamAdaptor has members which may
> have destructors that throw (e.g. they're not my code, it has
> one member which is a google protocol buffer class). If it's
> a 3rd party class that is throwing in its destructor, can I
> handle that safely? Oh, I guess I can release the pointer in
> my destructor surrounded by a try-catch...
>
> I'm using Eclipse-CDT, and it doesn't have a way to tell GDB
> to stop on an exception (I'm used to using Visual Studio
> which does have this feature). Setting a breakpoint on that
> constructor sounds like a good idea, should have thought of that.
>
> Thx.
>
> - Alex

Thanks, that fixed it!

My destructor now looks like this:

        try
        {
                m_pProtoBufStream.reset();
        }
        catch ( std::exception& e )
        {
                cout << endl << "Unexpected exception in ProtoBufStreamAdaptor::~ProtoBufStreamAdaptor: " << e.what() << endl;
        }
        catch ( ... )
        {
                cout << endl << "Unexpected exception in ProtoBufStreamAdaptor::~ProtoBufStreamAdaptor" << endl;
        }

And it does indeed catch an exception. Now my process doesn't die.

- Alex


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net