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

(Response below)
Alex Black wrote:
(Response is below)
On Tue, Jul 14, 2009 at 7:49 PM, Alex Black<alex@alexblack.ca> wrote:
I'm using boost::asio for sockets, writing a response out to a client. If the client stops part way through getting the response, then my server process dies:
terminate called after throwing an instance of
'boost::exception_detail::clone_impl<boost::exception_detail::error_in
fo_injector<boost::system::system_error> > ' ? what():? Broken pipe
The code though is surrounded by try catch like this:
try { ??? ... } catch ( std::exception& e ) { ??? cout << e.what() << endl; } catch ( ... ) { ???? cout << "unexpected exception" << endl; }
How do I prevent my process from aborting/terminating like this? v
Have you verified that the code inside the try block executes on the same thread that the exception is occuring in?
Not explicitly, how would I do that?
thx
First put a breakpoint inside the try block. When it gets hit use whatever mechanism your debugger provides to see what thread you're in. In windows using MSVC, for example, you'd just add a watch for a variable called $TID which a special pseudo-variable that shows you the thread id. For other debuggers you'd have to consult the manual. Next register an unhandled exception handler.
#include <exception>
void unhandled_exception_handler() { std::cout << "Got an unhandled exception!" << std::endl; }
int main(int argc, char** argv) { std::set_terminate(unhandled_exception_handler);
//rest of your program. }
Then put a breakpoint inside unhandled_exception_handler and when it gets hit walk up the callstack in the debugger to see where the exception is occuring. In addition you can determine the thread id again using the same method you used in the first step. My guess is that they're not in the same thread. I'm not sure if it applies to your scenario, but remember that the operation's completion handler is invoked on is not necessarily the same thread that the request is issued on depending on how you're using the io_service object. So while you have a try {} catch(...) {} in the completion handler, if the exception is on the other thread that does you no good.
Thanks for the tip, I didn't know about set_terminate, I made that change.
I put a breakpoint in my terminate handler, and the callstack looks like:
32 unhandled_exception_handler() /home/noirs/workspace/myfile.cpp:35 0x0000000000438764 31 <symbol is not available> 0x00007f9ceb0d04b6 30 <symbol is not available> 0x00007f9ceb0cf6ab 29 __gxx_personality_v0() 0x00007f9ceb0d0278 28 <symbol is not available> 0x00007f9ceab7cff3 27 _Unwind_Resume() 0x00007f9ceab7d0b8 26 ~ProtoBufStreamAdaptor() /home/noirs/workspace/myfile2.cpp:10 0x000000000042c6e5 25 CWebServer::HandleGetNeighbors() /home/noirs/workspace/myfile3.cpp:215 0x000000000041d2d8 24 CWebServer::OnHttpRequest() /home/noirs/workspace/myfile3.cpp:89 0x000000000041e790 23 CBaseWebServer::HandleHTTPRequest() /home/noirs/workspace/myfile4.cpp:92 0x00000000004092ef 22 CBaseWebServer::HandleAccept() /home/noirs/workspace/myfile4.cpp:61 0x0000000000409a9e
HandleAccept looks like:
void CBaseWebServer::HandleAccept(shared_ptr<tcp::socket> pSocket, const boost::system::error_code& error) { if ( !error ) { try { HandleHTTPRequest(pSocket);
StartAccept(); } catch ( ... ) { cout << "Unhandled exception in HandleAccept"; } } else { cout << "HandleAccept received error: " << error.message().c_str() << endl; } } _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
Um, broken pipe = closed file desciptor.
Check if the socket is actually valid in the shard_ptr...
BTW, are you using Async operations.... if so then the exception will not originate from your code but from io_service.run().
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"; } }

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.
participants (2)
-
Alex Black
-
Zachary Turner