Opened 12 years ago

Closed 10 years ago

#5012 closed Bugs (wontfix)

pthread_exit from child thread causes boost:thread:join in main thread to lock up

Reported by: Slava <Viatcheslav.Sysoltsev@…> Owned by: viboes
Milestone: To Be Determined Component: thread
Version: Boost Development Trunk Severity: Problem
Keywords: Cc:

Description

Current design of thread_proxy thread/src/pthread/thread.cpp assumes strongly, the child thread does "return" from supplied user routine or uses boost::thread insterruption facilities. Well, wrong assumption, the thread may use pthread_exit() to *gently* exit single thread. On Linux at least the pthread_exit throws special forced_unwind exception, which causes stack unwinding and is caucht in ?libc to accurately finalize the thread. This goes wrong with boost::thread implementation which does not expect the execution to bypass the code after user thread callback function and still not be ending the whole process.

Here is the test case to illustrate:

#include <boost/thread.hpp>

void tf()
{
    pthread_exit(NULL);
}


int main()
{
    boost::thread t(tf);
    t.join();
    return  0;
}

> g++ -g -O0 -I/home/vsysolts/boost/boost-trunk test2.cpp -L/home/vsysolts/boost/boost-trunk/stage/lib -lboost_thread && gdb a.out
GNU gdb (GDB) 7.2
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-unknown-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/vsysolts/test/boost_thread/a.out...done.
(gdb) r
Starting program: /home/vsysolts/test/boost_thread/a.out 
[Thread debugging using libthread_db enabled]
[New Thread 0x7ffff6cb6950 (LWP 13426)]
[Thread 0x7ffff6cb6950 (LWP 13426) exited]
^C
Program received signal SIGINT, Interrupt.
0x00007ffff6cc1d59 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
(gdb) bt
#0  0x00007ffff6cc1d59 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
#1  0x00007ffff7bd4a73 in boost::condition_variable::wait (this=0x60c128, m=...) at ./boost/thread/pthread/condition_variable.hpp:53
#2  0x00007ffff7bcbbd8 in boost::thread::join (this=0x7fffffffe0c0) at libs/thread/src/pthread/thread.cpp:215
#3  0x00000000004047cd in main () at test2.cpp:12
(gdb) quit

The thread:join is locked up in local_thread_info->done_condition.wait(lock); which is never signaled, because the child thread exited, bypassing the cleanup code in thread_proxy after user-specified thread callback. The right solution would be not to assume user-specified thread callback always return or throw boost::thread_interrupted exception, but use pthread_cleanup_push functionality to register thread cleanup handler necessary for additional boost::thread facilities.

You may be interested to see the preceeding boost-user discussion: http://thread.gmane.org/gmane.comp.lib.boost.user/64595

Environment: Boost trunk, rev 67410, gcc 4.3.2, openSUSE 11.1, x86_64 architecture.

Change History (2)

comment:1 by viboes, 11 years ago

Owner: changed from Anthony Williams to viboes
Status: newassigned

comment:2 by viboes, 10 years ago

Resolution: wontfix
Status: assignedclosed

I don't know how to fix this issue on all the platforms. Please, don't use pthread_exit. It doesn't clean up the thread's stack properly in a portable way.

Note: See TracTickets for help on using tickets.