Boost logo

Boost :

Subject: [boost] [thread] thread_proxy's catch(...) destroys my stack info for unhandled exceptions
From: Roberto Gimenez (chilabot_at_[hidden])
Date: 2008-12-26 14:49:55


When some unhandled exception is thrown inside my function, it would be good
that is isn't actually handled, so I could collect the stack info from the
core-dump. For example:

#include <boost/thread.hpp>

using namespace std;
using namespace boost;

void f1() { throw 1; }
void f2() { throw 1; }
void f() { f1(); f2(); }

int main(int argc, char** argv)
{
    
    thread t(f);
    t.join();
    
    return (EXIT_SUCCESS);
}

Whe run it, the core-dump's stack info is:

----------------- lwp# 1 / thread# 1 --------------------
 ffffffff7ecd2f20 __lwp_park (100108658, 100108640, ...
 ffffffff7eccc748 cond_wait_queue (100108658, 100108640, ...
 ffffffff7ecccca8 cond_wait (100108658, 100108640, ...
 ffffffff7ecccce4 pthread_cond_wait (100108658, 100108640,...
 ffffffff7f809ff4 void boost::thread::join() (ffffffff7ffff518, ...
 0000000100004168 main (1, ffffffff7ffff608, ffffffff7ffff618, ...
 0000000100003a7c _start (0, 0, 0, 0, 0, 0) + 17c
----------------- lwp# 2 / thread# 2 --------------------
 ffffffff7ecd40a4 _lwp_kill (6, 0, ffffffff7edf7338, ...
 ffffffff7ec4a68c abort (1, 1b8, ffffffff7f106f10, ...
 ffffffff7f106a04 void __Cimpl::default_terminate() (0, 0, ...
 ffffffff7f809770 thread_proxy (100108610, 1001086dd, 2c, ...
 ffffffff7ecd2e7c _lwp_start (0, 0, 0, 0, 0, 0)

With this information I cannot know where the exception was thrown.

So I commented the catch(...) part in libs/thread/src/pthread/thread.cpp:

extern "C"
{
    void* thread_proxy(void* param)
    {
        boost::detail::thread_data_ptr thread_info =
                static_cast<boost::detail::thread_data_base*>(param)->self;
        thread_info->self.reset();
        detail::set_current_thread_data(thread_info.get());
        try
        {
            thread_info->run();
        }
        catch(thread_interrupted const&)
        {
        }
        //catch(...)
        //{
        // std::terminate();
        //}

        detail::tls_destructor(thread_info.get());
        detail::set_current_thread_data(0);
        boost::lock_guard<boost::mutex> lock(thread_info->data_mutex);
        thread_info->done=true;
        thread_info->done_condition.notify_all();
        return 0;
    }
}

And recompiled boost, now the core dump's stack info is the desired one:

----------------- lwp# 1 / thread# 1 --------------------
 ffffffff7ecd2f20 __lwp_park (100108658, 100108640, 0, 4, 11fb1c, ...
 ffffffff7eccc748 cond_wait_queue (100108658, 100108640, 0, 0, ...
 ffffffff7ecccca8 cond_wait (100108658, 100108640, ffffffff7ed00358,...
 ffffffff7ecccce4 pthread_cond_wait (100108658, 100108640, ...
 ffffffff7f809f54 void boost::thread::join() (ffffffff7ffff518, ...
 0000000100004168 main (1, ffffffff7ffff608, ffffffff7ffff618, ...
 0000000100003a7c _start (0, 0, 0, 0, 0, 0) + 17c
----------------- lwp# 2 / thread# 2 --------------------
 ffffffff7ecd40a4 _lwp_kill (6, 0, ffffffff7edf7338, ...
 ffffffff7ec4a68c abort (1, 1b8, ffffffff7f106f10, ...
 ffffffff7f106a04 void __Cimpl::default_terminate() (ffffffff7f214718, ...
 ffffffff7f1067f4 void __Cimpl::ex_terminate() (ffffffff7f2106c0, 0, 0, ...
 ffffffff7f1074c8 _ex_throw_body (ffffffff7f2106c0, 0, ffffffff7e2fbf50, ...
 ffffffff7f10740c void __Crun::ex_throw(void*,...
 0000000100004064 void f1() (0, 0, ffffffff7edf7f80, ...
 00000001000040fc void f() (ffffffff7f915528, 100108610, ...
 00000001000053c0 void boost::detail::thread_data<void(*)()>::run() (...
 ffffffff7f8095b4 thread_proxy (100108610, 3, 100106bd8, 100108610...
 ffffffff7ecd2e7c _lwp_start (0, 0, 0, 0, 0, 0)

I can know now where the unexpected/unhandled exception was thrown.
I could solve my problem partially, puting throw() exception specs
everywhere, so when some unexpected exception is thrown, the throw()
will stop it. Unfortunatelly, it whould stop at the calling function,
and the stack will tell me that some unexpected exception was thrown
by any of the functions inside the caller. This is worse than having
a stack info like the above one because in this case I wouldn't know
who raised the unexpected exception. In the above stack info I can know
who did it.

So why is:

catch(...)
{
    std::terminate();
}

there? It looks unnecesary.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk