Bug 23591 - exceptions in plugins in threads cause segmentation violation by leaving bad exit handler for the pthread
Summary: exceptions in plugins in threads cause segmentation violation by leaving bad ...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: libstdc++ (show other bugs)
Version: 3.3.5
: P3 normal
Target Milestone: 4.1.0
Assignee: Benjamin Kosnik
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2005-08-27 04:42 UTC by grothoff@gnunet.org
Modified: 2006-01-10 17:26 UTC (History)
1 user (show)

See Also:
Host: i486-pc-linux-gnu
Target: i486-pc-linux-gnu
Build: i486-pc-linux-gnu
Known to work:
Known to fail:
Last reconfirmed: 2005-10-16 01:16:46


Attachments
reproducer (1.00 KB, application/x-bzip2)
2005-10-20 05:09 UTC, Benjamin Kosnik
Details
tentative patch (6.09 KB, patch)
2005-11-09 18:36 UTC, Benjamin Kosnik
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description grothoff@gnunet.org 2005-08-27 04:42:01 UTC
libstdc++ registers some handlers with pthreads in conjunction
with throw statements.  Those handlers are not properly removed
when libstdc++ is unloaded, causing pthread_join to jump to a
bad address.

gcc -ldl -lpthread main.c -o main
g++ -shared -lstdc++ -lc -lm plug.cc \
-o plug.so
./main
In plug.
Leaving plug.
make: *** [all] Killed

gdb:

grothoff@elma:~/svn/bug905$ gdb main
GNU gdb 6.3-debian
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386-linux"...Using host libthread_db library "/usr/lib/debug/libthread_db.so.1".

(gdb) run
Starting program: /home/grothoff/svn/bug905/main
[Thread debugging using libthread_db enabled]
[New Thread 16384 (LWP 2816)]
[New Thread 32769 (LWP 2819)]
[New Thread 16386 (LWP 2821)]
In plug.
Leaving plug.

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 16386 (LWP 2821)]
0x557982a0 in ?? ()
(gdb) ba
#0  0x557982a0 in ?? ()
#1  0x55579f08 in __pthread_destroy_specifics () at specific.c:192
#2  0x555764d5 in __pthread_do_exit (retval=0x804cf18, currentframe=0x804cf18 "") at join.c:43
#3  0x55576e5d in pthread_start_thread (arg=0xff7ffbe0) at manager.c:312
#4  0x55576ecf in pthread_start_thread_event (arg=0xff7ffbe0) at manager.c:333
#5  0x5569992a in clone () from /usr/lib/debug/libc.so.6

Additional information about the original context is tracked in GNUnet's Mantis
bug database at https://gnunet.org/mantis/view.php?id=905

Environment:
System: Linux elma 2.6.8-11-amd64-k8 #1 Mon May 30 22:15:15 UTC 2005 x86_64 GNU/Linux
Architecture: x86_64 (also reproduced on i686)

	
host: i486-pc-linux-gnu
build: i486-pc-linux-gnu
target: i486-pc-linux-gnu
configured with: ../src/configure -v --enable-languages=c,c++,java,f77,pascal,objc,ada,treelang --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-gxx-include-dir=/usr/include/c++/3.3 --enable-shared --enable-__cxa_atexit --with-system-zlib --enable-nls --without-included-gettext --enable-clocale=gnu --enable-debug --enable-java-gc=boehm --enable-java-awt=xlib --enable-objc-gc i486-linux

How-To-Repeat:

Essentially, use C code that is NOT linked against libstdc++ to
create a pthread.  In that thread dlopen a C++ library, dlsym a 
function that throws and catches an exception, close the library.
In the main C code join on the pthread.  The join will segfault
after the C++ code is complete and the library is unloaded.

https://gnunet.org/svn/bug905/ has 60 lines of C and C++ code 
(plus a trivial Makefile) to reproduce.

What seems to happen is this.  libstdc++ registers some on-exit
handler with the pthread which refers to code in libstdc++. 
The library _fails_ to unregister that handler when libstdc++
itself is unloaded.  The library is unloaded, the handler is
still there, and on pthread_join the handler is called and
points to a (now invalid) address in memory => seg fault.

The bug was found in real-life in GNUnet (100% C, multithreaded) 
loading a C plugin which uses libextractor (reentrant) which 
loads a C++ plugin which uses exceptions.
Comment 1 grothoff@gnunet.org 2005-08-27 04:42:01 UTC
Fix:

Workarounds:
LD_PRELOAD libstdc++ (then the symbol stays in memory)
do not use pthreads (no exit handler)
do not use plugins (no unloading issue)
do not use exceptions (no handler registered)
link the C code against libstdc++ (handler stays in memory on unload of plugin)
do not use libstdc++ (yeah, right)

None of these is acceptable for me since C code that may load
a plugin that may load a plugin that may use C++ that may use
exceptions should not require C++ to be even _installed_, not
to mention link against it.

The solution is to properly track installed handlers and 
unregister those in the destructor of the library (ELF has
wonderful provisions for that).
Comment 2 Benjamin Kosnik 2005-09-12 19:05:40 UTC
I believe this is yet another manifestation of 22309.
Comment 3 Benjamin Kosnik 2005-10-20 05:09:32 UTC
Created attachment 10030 [details]
reproducer
Comment 4 Benjamin Kosnik 2005-10-20 05:11:59 UTC
Confirmed with gcc-4.x. This is unrelated to 22309.
Comment 5 Benjamin Kosnik 2005-11-09 18:36:13 UTC
Created attachment 10190 [details]
tentative patch
Comment 6 Benjamin Kosnik 2005-11-22 06:54:14 UTC
Subject: Bug 23591

Author: bkoz
Date: Tue Nov 22 06:54:08 2005
New Revision: 107350

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=107350
Log:
2005-11-21  Benjamin Kosnik  <bkoz@redhat.com>
            Ulrich Drepper  <drepper@redhat.com>

	PR libstdc++/23591
	* scripts/create_testsuite_files: Support for "C" test files.
	* testsuite/lib/libstdc++.exp: Same.
	* testsuite/libstdc++-dg/normal.exp: Same.
	* testsuite/ext/mt_allocator/22309_thread.cc: Update names.
	* testsuite/19_diagnostics/23591_thread-1.c: New.
	* testsuite/testsuite_shared.cc: Add tests, rename existing functions.
	* libsupc++/eh_globals.cc: Make global thread local if possible.
	* configure.ac: Use GCC_CHECK_TLS.
	* acinclude.m4: Include tls.m4.
	* configure: Regenerate.
	* config.h.in: Same.


Added:
    trunk/libstdc++-v3/testsuite/19_diagnostics/23591_thread-1.c
Modified:
    trunk/libstdc++-v3/ChangeLog
    trunk/libstdc++-v3/Makefile.in
    trunk/libstdc++-v3/acinclude.m4
    trunk/libstdc++-v3/aclocal.m4
    trunk/libstdc++-v3/config.h.in
    trunk/libstdc++-v3/configure
    trunk/libstdc++-v3/configure.ac
    trunk/libstdc++-v3/include/Makefile.in
    trunk/libstdc++-v3/libmath/Makefile.in
    trunk/libstdc++-v3/libsupc++/Makefile.in
    trunk/libstdc++-v3/libsupc++/eh_globals.cc
    trunk/libstdc++-v3/po/Makefile.in
    trunk/libstdc++-v3/scripts/create_testsuite_files
    trunk/libstdc++-v3/src/Makefile.in
    trunk/libstdc++-v3/testsuite/Makefile.in
    trunk/libstdc++-v3/testsuite/ext/mt_allocator/22309_thread.cc
    trunk/libstdc++-v3/testsuite/lib/libstdc++.exp
    trunk/libstdc++-v3/testsuite/libstdc++-dg/normal.exp
    trunk/libstdc++-v3/testsuite/testsuite_shared.cc

Comment 7 Benjamin Kosnik 2006-01-10 17:14:08 UTC
Subject: Bug 23591

Author: bkoz
Date: Tue Jan 10 17:14:00 2006
New Revision: 109545

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=109545
Log:
2006-01-10  Benjamin Kosnik  <bkoz@redhat.com>
            Ulrich Drepper  <drepper@redhat.com>

	PR libstdc++/23591
	* scripts/create_testsuite_files: Support for "C" test files.
	* testsuite/lib/libstdc++.exp: Same.
	* testsuite/libstdc++-dg/normal.exp: Same.
	* testsuite/ext/mt_allocator/22309_thread.cc: Update names.
	* testsuite/19_diagnostics/23591_thread-1.c: New.
	* testsuite/testsuite_shared.cc: Add tests, rename existing functions.
	* libsupc++/eh_globals.cc: Make global thread local if possible.
	* configure.ac: Use GCC_CHECK_TLS.
	* acinclude.m4: Include tls.m4.
	* configure: Regenerate.
	* config.h.in: Same.


Added:
    branches/gcc-4_1-branch/libstdc++-v3/testsuite/19_diagnostics/23591_thread-1.c
Modified:
    branches/gcc-4_1-branch/libstdc++-v3/ChangeLog
    branches/gcc-4_1-branch/libstdc++-v3/Makefile.in
    branches/gcc-4_1-branch/libstdc++-v3/acinclude.m4
    branches/gcc-4_1-branch/libstdc++-v3/aclocal.m4
    branches/gcc-4_1-branch/libstdc++-v3/config.h.in
    branches/gcc-4_1-branch/libstdc++-v3/configure
    branches/gcc-4_1-branch/libstdc++-v3/configure.ac
    branches/gcc-4_1-branch/libstdc++-v3/include/Makefile.in
    branches/gcc-4_1-branch/libstdc++-v3/libmath/Makefile.in
    branches/gcc-4_1-branch/libstdc++-v3/libsupc++/Makefile.in
    branches/gcc-4_1-branch/libstdc++-v3/libsupc++/eh_globals.cc
    branches/gcc-4_1-branch/libstdc++-v3/po/Makefile.in
    branches/gcc-4_1-branch/libstdc++-v3/scripts/create_testsuite_files
    branches/gcc-4_1-branch/libstdc++-v3/src/Makefile.in
    branches/gcc-4_1-branch/libstdc++-v3/testsuite/Makefile.in
    branches/gcc-4_1-branch/libstdc++-v3/testsuite/ext/mt_allocator/22309_thread.cc
    branches/gcc-4_1-branch/libstdc++-v3/testsuite/lib/libstdc++.exp
    branches/gcc-4_1-branch/libstdc++-v3/testsuite/libstdc++-dg/normal.exp
    branches/gcc-4_1-branch/libstdc++-v3/testsuite/testsuite_shared.cc

Comment 8 Benjamin Kosnik 2006-01-10 17:25:53 UTC
Fixed in 4.1.x and mainline.

There is another found while looking at this bug, in that multi-threaded apps with multiple, pending exceptions will leak active and in-flight exceptions at termination.

I'll open a separate bug report for that.
Comment 9 Benjamin Kosnik 2006-01-10 17:26:58 UTC
Fixed.