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:09:18


> >> 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


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