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.
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).
I believe this is yet another manifestation of 22309.
Created attachment 10030 [details] reproducer
Confirmed with gcc-4.x. This is unrelated to 22309.
Created attachment 10190 [details] tentative patch
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
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
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.
Fixed.