Re: [Boost-users] Unable to catch exception using boost::asio

Message: 3 Date: Wed, 15 Jul 2009 10:56:22 -0500 From: Zachary Turner <divisortheory@gmail.com> Subject: Re: [Boost-users] Unable to catch exception using boost::asio To: boost-users@lists.boost.org Message-ID: <478231340907150856x12c9fd92w3b06630d349eef36@mail.gmail.com> 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@lists.boost.org 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.

On Wed, Jul 15, 2009 at 10:10 AM, Alex Black <alex@alexblack.ca> wrote:
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( ... )?
If a destructor calls functions that may throw, it should use catch(...) and not let exceptions propagate out of the destructor itself. However, when writing or sending data, the user may want to know that the operation has completed successfully. Typically, you'd provide a separate flush function for that use case, which you'd then call in the destructor, as in: foo_sender::~foo_sender() { try { flush(); } catch(...) { } } Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode

Thanks for the tip. However, my destructors are empty in this case.
-----Original Message----- From: boost-users-bounces@lists.boost.org [mailto:boost-users-bounces@lists.boost.org] On Behalf Of Emil Dotchevski Sent: Wednesday, July 15, 2009 1:21 PM To: boost-users@lists.boost.org Subject: Re: [Boost-users] Unable to catch exception using boost::asio
On Wed, Jul 15, 2009 at 10:10 AM, Alex Black <alex@alexblack.ca> wrote:
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( ... )?
If a destructor calls functions that may throw, it should use catch(...) and not let exceptions propagate out of the destructor itself. However, when writing or sending data, the user may want to know that the operation has completed successfully. Typically, you'd provide a separate flush function for that use case, which you'd then call in the destructor, as in:
foo_sender::~foo_sender() { try { flush(); } catch(...) { } }
Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

So when my app crashes, here is the message I see on the console: (if I don't have a set_terminate handler installed) terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info _injector<boost::system::system_error> >' what(): Broken pipe here is a more complete stack trace: (when I set a breakpoint in the set_terminate handler) EnginePrototype [C/C++ Application] gdb/mi (7/15/09 1:29 PM) (Suspended) Thread [1] (Suspended) Thread [2] (Suspended) Thread [3] (Suspended: Signal 'SIGABRT' received. Description: Aborted.) 34 raise() 0x00007f5dc63b6fb5 33 abort() 0x00007f5dc63b8bc3 32 <symbol is not available> 0x00007f5dc6c5a4bb 31 <symbol is not available> 0x00007f5dc6c596ab 30 __gxx_personality_v0() 0x00007f5dc6c5a278 29 <symbol is not available> 0x00007f5dc6706ff3 28 _Unwind_Resume() 0x00007f5dc67070b8 27 ~ProtoBufStreamAdaptor() /home/noirs/workspace/projectPrototype/EnginePrototype/src/web/ProtoBufS treamAdaptor.cpp:10 0x000000000042c75d 26 CEngineWebServer::HandleGetNeighbors() /home/noirs/workspace/projectPrototype/EnginePrototype/src/web/EngineWeb Server.cpp:215 0x000000000041d350 25 CEngineWebServer::OnHttpRequest() /home/noirs/workspace/projectPrototype/EnginePrototype/src/web/EngineWeb Server.cpp:89 0x000000000041e808 24 CBaseWebServer::HandleHTTPRequest() /home/noirs/workspace/projectPrototype/EnginePrototype/src/web/BaseWebSe rver.cpp:105 0x00000000004092af 23 CBaseWebServer::HandleAccept() /home/noirs/workspace/projectPrototype/EnginePrototype/src/web/BaseWebSe rver.cpp:74 0x0000000000409aaa 22 boost::_mfi::mf2<void, CBaseWebServer, boost::shared_ptr<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > >, boost::system::error_code const&>::operator() /home/noirs/workspace/projectPrototype/boost_1_39_0/boost/bind/mem_fn_te mplate.hpp:274 0x000000000040eb2c 21 boost::_bi::list3<boost::_bi::value<CBaseWebServer*>, boost::_bi::value<boost::shared_ptr<boost::asio::basic_stream_socket<boo st::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > > >, boost::arg<1> (*)()>::operator()<boost::_mfi::mf2<void, CBaseWebServer, boost::shared_ptr<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > >, boost::system::error_code const&>, boost::_bi::list1<boost::system::error_code&> >() /home/noirs/workspace/projectPrototype/boost_1_39_0/boost/bind/bind.hpp: 385 0x000000000040ed1e 20 boost::_bi::bind_t<void, boost::_mfi::mf2<void, CBaseWebServer, boost::shared_ptr<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > >, boost::system::error_code const&>, boost::_bi::list3<boost::_bi::value<CBaseWebServer*>, boost::_bi::value<boost::shared_ptr<boost::asio::basic_stream_socket<boo st::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > > >, boost::arg<1> (*)()> >::operator()<boost::system::error_code>() /home/noirs/workspace/projectPrototype/boost_1_39_0/boost/bind/bind_temp late.hpp:32 0x000000000040ed92 19 boost::asio::detail::binder1<boost::_bi::bind_t<void, boost::_mfi::mf2<void, CBaseWebServer, boost::shared_ptr<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > >, boost::system::error_code const&>, boost::_bi::list3<boost::_bi::value<CBaseWebServer*>, boost::_bi::value<boost::shared_ptr<boost::asio::basic_stream_socket<boo st::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > > >, boost::arg<1> (*)()> >, boost::system::error_code>::operator() /home/noirs/workspace/projectPrototype/boost_1_39_0/boost/asio/detail/bi nd_handler.hpp:39 0x000000000040edb1 18 boost::asio::asio_handler_invoke<boost::asio::detail::binder1<boost::_bi ::bind_t<void, boost::_mfi::mf2<void, CBaseWebServer, boost::shared_ptr<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > >, boost::system::error_code const&>, boost::_bi::list3<boost::_bi::value<CBaseWebServer*>, boost::_bi::value<boost::shared_ptr<boost::asio::basic_stream_socket<boo st::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > > >, boost::arg<1> (*)()> >, boost::system::error_code> >() /home/noirs/workspace/projectPrototype/boost_1_39_0/boost/asio/handler_i nvoke_hook.hpp:63 0x000000000040ee4c 17 boost_asio_handler_invoke_helpers::invoke<boost::asio::detail::binder1<b oost::_bi::bind_t<void, boost::_mfi::mf2<void, CBaseWebServer, boost::shared_ptr<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > >, boost::system::error_code const&>, boost::_bi::list3<boost::_bi::value<CBaseWebServer*>, boost::_bi::value<boost::shared_ptr<boost::asio::basic_stream_socket<boo st::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > > >, boost::arg<1> (*)()> >, boost::system::error_code>, boost::_bi::bind_t<void, boost::_mfi::mf2<void, CBaseWebServer, boost::shared_ptr<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > >, boost::system::error_code const&>, boost::_bi::list3<boost::_bi::value<CBaseWebServer*>, boost::_bi::value<boost::shared_ptr<boost::asio::basic_stream_socket<boo st::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > > >, boost::arg<1> (*)()> > >() /home/noirs/workspace/projectPrototype/boost_1_39_0/boost/asio/detail/ha ndler_invoke_helpers.hpp:39 0x000000000040ee80 16 boost::asio::detail::asio_handler_invoke<boost::asio::detail::binder1<bo ost::_bi::bind_t<void, boost::_mfi::mf2<void, CBaseWebServer, boost::shared_ptr<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > >, boost::system::error_code const&>, boost::_bi::list3<boost::_bi::value<CBaseWebServer*>, boost::_bi::value<boost::shared_ptr<boost::asio::basic_stream_socket<boo st::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > > >, boost::arg<1> (*)()> >, boost::system::error_code>, boost::_bi::bind_t<void, boost::_mfi::mf2<void, CBaseWebServer, boost::shared_ptr<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > >, boost::system::error_code const&>, boost::_bi::list3<boost::_bi::value<CBaseWebServer*>, boost::_bi::value<boost::shared_ptr<boost::asio::basic_stream_socket<boo st::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > > >, boost::arg<1> (*)()> >, boost::system::error_code>() /home/noirs/workspace/projectPrototype/boost_1_39_0/boost/asio/detail/bi nd_handler.hpp:72 0x000000000040eed3 15 boost_asio_handler_invoke_helpers::invoke<boost::asio::detail::binder1<b oost::_bi::bind_t<void, boost::_mfi::mf2<void, CBaseWebServer, boost::shared_ptr<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > >, boost::system::error_code const&>, boost::_bi::list3<boost::_bi::value<CBaseWebServer*>, boost::_bi::value<boost::shared_ptr<boost::asio::basic_stream_socket<boo st::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > > >, boost::arg<1> (*)()> >, boost::system::error_code>, boost::asio::detail::binder1<boost::_bi::bind_t<void, boost::_mfi::mf2<void, CBaseWebServer, boost::shared_ptr<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > >, boost::system::error_code const&>, boost::_bi::list3<boost::_bi::value<CBaseWebServer*>, boost::_bi::value<boost::shared_ptr<boost::asio::basic_stream_socket<boo st::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > > >, boost::arg<1> (*)()> >, boost::system::error_code> >() /home/noirs/workspace/projectPrototype/boost_1_39_0/boost/asio/detail/ha ndler_invoke_helpers.hpp:39 0x000000000040eef2 14 boost::asio::detail::handler_queue::handler_wrapper<boost::asio::detail: :binder1<boost::_bi::bind_t<void, boost::_mfi::mf2<void, CBaseWebServer, boost::shared_ptr<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > >, boost::system::error_code const&>, boost::_bi::list3<boost::_bi::value<CBaseWebServer*>, boost::_bi::value<boost::shared_ptr<boost::asio::basic_stream_socket<boo st::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > > >, boost::arg<1> (*)()> >, boost::system::error_code> >::do_call() /home/noirs/workspace/projectPrototype/boost_1_39_0/boost/asio/detail/ha ndler_queue.hpp:192 0x00000000004109f4 13 boost::asio::detail::handler_queue::handler::invoke() /home/noirs/workspace/projectPrototype/boost_1_39_0/boost/asio/detail/ha ndler_queue.hpp:39 0x000000000040a67c 12 boost::asio::detail::task_io_service<boost::asio::detail::epoll_reactor< false> >::do_one() /home/noirs/workspace/projectPrototype/boost_1_39_0/boost/asio/detail/ta sk_io_service.hpp:268 0x000000000041a5fd 11 boost::asio::detail::task_io_service<boost::asio::detail::epoll_reactor< false> >::run() /home/noirs/workspace/projectPrototype/boost_1_39_0/boost/asio/detail/ta sk_io_service.hpp:103 0x000000000041a82a 10 boost::asio::io_service::run() /home/noirs/workspace/projectPrototype/boost_1_39_0/boost/asio/impl/io_s ervice.ipp:58 0x000000000041a95c 9 CBaseWebServer::RunIoService() /home/noirs/workspace/projectPrototype/EnginePrototype/src/web/BaseWebSe rver.cpp:37 0x0000000000409c3c 8 boost::_mfi::mf0<void, CBaseWebServer>::operator() /home/noirs/workspace/projectPrototype/boost_1_39_0/boost/bind/mem_fn_te mplate.hpp:49 0x000000000040e7c2 7 boost::_bi::list1<boost::_bi::value<CBaseWebServer*>
::operator()<boost::_mfi::mf0<void, CBaseWebServer>, boost::_bi::list0>() /home/noirs/workspace/projectPrototype/boost_1_39_0/boost/bind/bind.hpp: 246 0x000000000040e805 6 boost::_bi::bind_t<void, boost::_mfi::mf0<void, CBaseWebServer>, boost::_bi::list1<boost::_bi::value<CBaseWebServer*> > >::operator() /home/noirs/workspace/projectPrototype/boost_1_39_0/boost/bind/bind_temp late.hpp:20 0x000000000040e842 5 boost::detail::thread_data<boost::_bi::bind_t<void, boost::_mfi::mf0<void, CBaseWebServer>, boost::_bi::list1<boost::_bi::value<CBaseWebServer*> > > >::run() /home/noirs/workspace/projectPrototype/boost_1_39_0/boost/thread/detail/ thread.hpp:56 0x000000000040e860 4 thread_proxy() 0x00000000004d6818 3 start_thread() 0x00007f5dc6ea73ba 2 clone() 0x00007f5dc6469fcd 1 <symbol is not available> 0x0000000000000000 gdb (7/15/09 1:29 PM)
/home/noirs/workspace/projectPrototype/EnginePrototype/Debug/EngineProto type (7/15/09 1:29 PM) Here are some snippets from my code in that stack: void CBaseWebServer::RunIoService() { try { m_IoService.run(); } catch ( ... ) { cout << endl << "Unhandled exception in RunIoService" << endl; } } void CBaseWebServer::HandleAccept(shared_ptr<tcp::socket> pSocket, const boost::system::error_code& error) { if ( !error ) { try { HandleHTTPRequest(pSocket); StartAccept(); } catch ( ... ) { cout << endl << "Unhandled exception in HandleAccept" << endl; } } else { cout << endl << "HandleAccept received error: " << error.message().c_str() << endl; } }
-----Original Message----- From: boost-users-bounces@lists.boost.org [mailto:boost-users-bounces@lists.boost.org] On Behalf Of Emil Dotchevski Sent: Wednesday, July 15, 2009 1:21 PM To: boost-users@lists.boost.org Subject: Re: [Boost-users] Unable to catch exception using boost::asio
On Wed, Jul 15, 2009 at 10:10 AM, Alex Black <alex@alexblack.ca> wrote:
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( ... )?
If a destructor calls functions that may throw, it should use catch(...) and not let exceptions propagate out of the destructor itself. However, when writing or sending data, the user may want to know that the operation has completed successfully. Typically, you'd provide a separate flush function for that use case, which you'd then call in the destructor, as in:
foo_sender::~foo_sender() { try { flush(); } catch(...) { } }
Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

On Wed, Jul 15, 2009 at 12:10 PM, Alex Black<alex@alexblack.ca> wrote:
Message: 3 Date: Wed, 15 Jul 2009 10:56:22 -0500 From: Zachary Turner <divisortheory@gmail.com> Subject: Re: [Boost-users] Unable to catch exception using boost::asio To: boost-users@lists.boost.org Message-ID: <478231340907150856x12c9fd92w3b06630d349eef36@mail.gmail.com> 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@lists.boost.org 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.

Message: 3 Date: Wed, 15 Jul 2009 10:56:22 -0500 From: Zachary Turner <divisortheory@gmail.com> Subject: Re: [Boost-users] Unable to catch exception using boost::asio To: boost-users@lists.boost.org Message-ID: <478231340907150856x12c9fd92w3b06630d349eef36@mail.gmail.com> 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@lists.boost.org 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

Message: 3 Date: Wed, 15 Jul 2009 10:56:22 -0500 From: Zachary Turner <divisortheory@gmail.com> Subject: Re: [Boost-users] Unable to catch exception using boost::asio To: boost-users@lists.boost.org Message-ID: <478231340907150856x12c9fd92w3b06630d349eef36@mail.gmail.com> 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@lists.boost.org 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

On Wed, Jul 15, 2009 at 11:31 AM, Alex Black<alex@alexblack.ca> wrote:
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.
I'd replace this with: try { m_pProtoBufStream.reset(); } catch ( ... ) { cout << endl << "Unexpected exception caught in " << BOOST_CURRENT_FUNCTION << endl << boost::current_exception_diagnostic_information(); } (you'd need to #include <boost/exception/diagnostic_information.hpp>) Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode

Thanks for the suggestion, I was not aware of boost::current_exception_diagnostic_information(), looks useful!
-----Original Message----- From: boost-users-bounces@lists.boost.org [mailto:boost-users-bounces@lists.boost.org] On Behalf Of Emil Dotchevski Sent: Wednesday, July 15, 2009 2:42 PM To: boost-users@lists.boost.org Subject: Re: [Boost-users] Unable to catch exception using boost::asio
On Wed, Jul 15, 2009 at 11:31 AM, Alex Black<alex@alexblack.ca> wrote:
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.
I'd replace this with:
try { m_pProtoBufStream.reset(); } catch ( ... ) { cout << endl << "Unexpected exception caught in " << BOOST_CURRENT_FUNCTION << endl << boost::current_exception_diagnostic_information(); }
(you'd need to #include <boost/exception/diagnostic_information.hpp>)
Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

On Wed, Jul 15, 2009 at 11:05 AM, Zachary Turner<divisortheory@gmail.com> wrote:
On Wed, Jul 15, 2009 at 12:10 PM, Alex Black<alex@alexblack.ca> wrote: Some debuggers provide mechanisms so that you can stop at the exact point an exception is thrown, rather than where it is handled.
If the exception that's emitted is a Boost exception, you can intercept it before it is thrown by setting a break point in boost::throw_exception(). Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode
participants (3)
-
Alex Black
-
Emil Dotchevski
-
Zachary Turner