Bug 132049

Summary: pthread_exit on NPTL calls user defined termination handler during stack unwind
Product: Red Hat Enterprise Linux 3 Reporter: Tushar Telichari <tushar>
Component: glibcAssignee: Jakub Jelinek <jakub>
Status: CLOSED NOTABUG QA Contact: Brian Brock <bbrock>
Severity: medium Docs Contact:
Priority: medium    
Version: 3.0   
Target Milestone: ---   
Target Release: ---   
Hardware: i686   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2004-09-13 06:51:56 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Attachments:
Description Flags
Sample to reproduce the stack none

Description Tushar Telichari 2004-09-08 08:46:29 UTC
From Bugzilla Helper:
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.2)
Gecko/20040803

Description of problem:
Stack:

#0  0xb71393d8 in exit () from /lib/tls/libc.so.6
#1  0xb73dfcb4 in o_exit () from /release/6.0.5/lib/liboscfe.so
#2  0xb758acf2 in vpp_db_exit () from /release/6.0.5/lib/libcxxcls.so
#3  0xb7588602 in vpp_exit () from /release/6.0.5/lib/libcxxcls.so
#4  0xb7585726 in vpp_terminate() () from /release/6.0.5/lib/libcxxcls.so
#5  0xb72f4537 in __cxa_call_unexpected () from /usr/lib/libstdc++.so.5
#6  0xb72f4584 in std::terminate() () from /usr/lib/libstdc++.so.5
#7  0xb72f43ac in __gxx_personality_v0 () from /usr/lib/libstdc++.so.5
#8  0xb710a332 in _Unwind_RaiseException () from /lib/libgcc_s.so.1
#9  0xb710a3cb in _Unwind_ForcedUnwind () from /lib/libgcc_s.so.1
#10 0xb735a2f4 in _Unwind_ForcedUnwind () from /lib/tls/libpthread.so.0
#11 0xb7358443 in __pthread_unwind () from /lib/tls/libpthread.so.0
#12 0xb7354ae2 in pthread_exit () from /lib/tls/libpthread.so.0
#13 0x08196c39 in th2_main(void*) (par=0x83faf10) at a_thread_th2.C:813
#14 0xb7353dac in start_thread () from /lib/tls/libpthread.so.0
#15 0xb71eaa8a in clone () from /lib/tls/libc.so.6

vpp_terminate is our own termination handler set using
std::set_terminate.  

Our concern is that a pthread_exit call is leading to a call to
vpp_terminate when in fact no exception has been raised and the thread
is doing a normal pthread_exit(0).  The problem seems to be NPTL
specific, because if we set LD_ASSUME_KERNEL=2.4.19 in the environment
then the problem goes away.  

We feel that this could be a problem with pthread_exit in NPTL. 
Unfortunately we do not have a test case that reproduces this
behavior.  The crash happened at one of our customer sites and all we
have is the stack.  

We have 3 questions,
1) We would like to know why a pthread_exit is calling a user defined
termination handler when all it should do is cleanup thread specific
data and terminate the thread ?
2) Why is the problem occuring only on NPTL?
3) Is there any down side to using LD_ASSUME_KERNEL solution?




Version-Release number of selected component (if applicable):


How reproducible:
Couldn't Reproduce

Steps to Reproduce:
1. Not reproducable
2.
3.
    

Additional info:

Comment 1 Jakub Jelinek 2004-09-09 07:53:25 UTC
The standard doesn't specify how is pthread_exit supposed to handle
calling of the cleanups nor is there any standard covering both
POSIX threads and C++.
But forced unwinding (very similar to throwing an exception) is
closest to the spirit pthread_exit/cancellation and ensures that
e.g. C++ destructors are run.
Just make sure no caller (even indirect) of pthread_exit is throw()
and don't catch(...) it and it will work just fine.

Comment 2 Tushar Telichari 2004-09-10 05:46:29 UTC
We are sure that no caller of pthread_exit is throw().  Also, the 
application is working perfectly fine and no exceptions are 
generated.  This problem is occuring after the thread has cleanly 
done its job and then calls pthread_exit(0) to terminate.  

Please answer our third question which we asked in the earlier post,
 Is there any down side to using LD_ASSUME_KERNEL solution?


Comment 3 Tushar Telichari 2004-09-13 06:25:58 UTC
Created attachment 103779 [details]
Sample to reproduce the stack

Comment 4 Tushar Telichari 2004-09-13 06:41:55 UTC
To reproduce the stack we have compiled and executed the attached 
sample on different RedHat releases,

We compiled on,
Red Hat Linux release 8.0 (Psyche)
Kernel 2.4.18-14smp on an i686
glibc-2.2.93-5
glibc-kernheaders-2.4-7.20
glibc-common-2.2.93-5
glibc-devel-2.2.93-5

We compile the code with command,
g++ -lpthread pthread1.cpp

We are executing on,
Linux release 2.4.21-4.ELsmp #1 SMP Fri Oct 3 17:52:56 EDT 2003 (0)
glibc-devel-2.3.2-95.3
glibc-common-2.3.2-95.3
glibc-utils-2.3.2-95.3
glibc-headers-2.3.2-95.3
glibc-2.3.2-95.3
glibc-profile-2.3.2-95.3
glibc-kernheaders-2.4-8.34


The the program aborts during pthread_exit() and the stack is,
(gdb) bt
#0  0xb75ebc32 in _dl_sysinfo_int80 () from /lib/ld-linux.so.2
#1  0xb73dea09 in raise () from /lib/tls/libc.so.6
#2  0xb73e0235 in abort () from /lib/tls/libc.so.6
#3  0xb75a4487 in __cxa_call_unexpected () 
from /usr/lib/libstdc++.so.5
#4  0xb75a44d4 in std::terminate() () from /usr/lib/libstdc++.so.5
#5  0xb75a42fc in __gxx_personality_v0 () from /usr/lib/libstdc++.so.5
#6  0xb74f2332 in _Unwind_RaiseException () from /lib/libgcc_s.so.1
#7  0xb74f23cb in _Unwind_ForcedUnwind () from /lib/libgcc_s.so.1
#8  0xb75d72a4 in _Unwind_ForcedUnwind () 
from /lib/tls/libpthread.so.0
#9  0xb75d5486 in __pthread_unwind () from /lib/tls/libpthread.so.0
#10 0xb75d1ae2 in pthread_exit () from /lib/tls/libpthread.so.0
#11 0x08048b9b in print_message_function(void*) ()
#12 0xb75d0dac in start_thread () from /lib/tls/libpthread.so.0
#13 0xb74919ea in clone () from /lib/tls/libc.so.6



Comment 5 Jakub Jelinek 2004-09-13 06:51:56 UTC
RHL8 pthread.h was buggy, it had incorrectly throw() on pthread_exit
and a couple of other prototypes which must not have it.
If you compile this on RHEL3, it will work just fine.

BTW, if all you need pthread_exit for is calling it at the very end
of thread handler function passed to pthread_exit, consider removing it
and instead return the value passed to pthread_exit.
That is much more efficient.

If you for some reason really need to compile on RHL8 (which is no
longer supported), you can apply:
http://sources.redhat.com/cgi-bin/cvsweb.cgi/libc/linuxthreads/sysdeps/pthread/pthread.h.diff?r1=1.34&r2=1.35&cvsroot=glibc
http://sources.redhat.com/cgi-bin/cvsweb.cgi/libc/linuxthreads/sysdeps/pthread/pthread.h.diff?r1=1.36&r2=1.37&cvsroot=glibc
http://sources.redhat.com/cgi-bin/cvsweb.cgi/libc/linuxthreads/sysdeps/pthread/pthread.h.diff?r1=1.38&r2=1.39&cvsroot=glibc
to /usr/include/pthread.h.