GDB and libthr

Doug Rabson dfr at nlsystems.com
Mon Oct 13 06:44:43 PDT 2003


I just upgraded one of my systems to the latest current and I came
across some problems with libthr. A program which I was working on
suddenly found itself linked against libthr (presumably because of a new
version of libmap.conf or similar) and I found myself completely unable
to debug it. This was not a threaded application, merely one which had
linked against libthr.

The symtoms are that when running the application under gdb, it quickly
hangs and starts consuming as much CPU time as it can. I looked into
things carefully and at the bottom of things, I discovered that when a
libthr mutex is held, the process blocks out SIGTRAP (among other
things). If the application hits a breakpoint while the mutex is held,
everything quickly goes pear shaped since the application doesn't get
the SIGTRAP. Basically it gets into a tight loop of hitting the
breakpoint, getting a signal, ignoring it and then trying to execute the
breakpoint instruction again.

Since this also happens when dlopen is called (there is always a
breakpoint inside the dynamic linker to keep GDB's list of shared
libraries up to date) and since comon apis such as getpwuid end up in
dlopen via nsdispatch, it becomes impossible to run many applications
even without setting breakpoints. Also, if an application happens to
take a non-recoverable fatal signal such as SIGSEGV, SIGBUS, SIGSYS or
similar while holding a mutex, it will wedge itself in a tight loop in a
similar way, whether or not it is running under GDB.

The simplest change which fixed things for me was to remove SIGTRAP from
the list of signals blocked on mutex entry. This does not fix the
similar problems with SIGSEGV etc.

Index: thr_kern.c
===================================================================
RCS file: /home/ncvs/src/lib/libthr/thread/thr_kern.c,v
retrieving revision 1.13
diff -u -r1.13 thr_kern.c
--- thr_kern.c  8 Jul 2003 09:58:23 -0000       1.13
+++ thr_kern.c  12 Oct 2003 12:05:39 -0000
@@ -80,6 +80,7 @@
 #ifdef _PTHREADS_INVARIANTS
        SIGDELSET(set, SIGABRT);
 #endif
+       SIGDELSET(set, SIGTRAP);
 
        /* If we have already blocked signals, just up the refcount */
        if (++curthread->signest > 1)





More information about the freebsd-threads mailing list