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:

[EMAIL PROTECTED]:~/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.
------- Additional Comments From grothoff at gnunet dot org  2005-08-27 04:42 
-------
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).

-- 
           Summary: exceptions in plugins in threads cause segmentation
                    violation by leaving bad exit handler for the pthread
           Product: gcc
           Version: 3.3.5
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: libstdc++
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: grothoff at gnunet dot org
                CC: gcc-bugs at gcc dot gnu dot org
 GCC build triplet: i486-pc-linux-gnu
  GCC host triplet: i486-pc-linux-gnu
GCC target triplet: i486-pc-linux-gnu


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=23591

Reply via email to