>Number: 6417
>Category: library
>Synopsis: pthread_exit() final thread hangs
>Confidential: yes
>Severity: serious
>Priority: medium
>Responsible: bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: unknown
>Arrival-Date: Wed Jun 30 12:00:01 GMT 2010
>Closed-Date:
>Last-Modified:
>Originator:
>Release:
>Organization:
>Environment:
System : OpenBSD 4.6
Details : OpenBSD 4.6 (GENERIC) #43: Thu Jul 9 21:34:21 MDT
2009 [email protected]:/usr/src/sys/arch/sparc64/compile/GENERIC
Architecture: OpenBSD.sparc64
Machine : sparc64
>Description:
After creating one mutex and two threads, pthread_exit() hangs
on the final thread.
The code works fine without creating that mutex.
>How-To-Repeat:
Code to trigger.
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
void* run(void* arg)
{
(void)arg;
return NULL;
}
int main(void)
{
pthread_t t[10];
int i, num=2;
pthread_mutex_t m;
printf("mutex init\n");
pthread_mutex_init(&m, NULL);
printf("pthread create %d threads\n", num);
for(i=0; i<num; i++) {
pthread_create(&t[i], NULL, run, NULL);
}
for(i=0; i<num; i++) {
pthread_join(t[i], NULL);
}
printf("pthread joined %d threads\n", num);
pthread_mutex_destroy(&m);
printf("mutex destroyed\n");
printf("pthread_exit\n");
pthread_exit(NULL);
}
then gcc -pthread the file and run. It does not exit. gdb says
#0 0x00000000479903e8 in poll () from /usr/lib/libc.so.51.0
#1 0x0000000047325d6c in _thread_kern_poll (wait_reqd=0)
at /usr/src/lib/libpthread/uthread/uthread_kern.c:760
#2 0x0000000047325770 in _thread_kern_sched (scp=0x0)
at /usr/src/lib/libpthread/uthread/uthread_kern.c:382
#3 0x00000000473230c4 in pthread_cond_timedwait (cond=0x4752c110,
mutex=0x4752c108, abstime=0x4b861e70)
at /usr/src/lib/libpthread/uthread/uthread_cond.c:431
#4 0x000000004731afb4 in _thread_gc (arg=0x0)
at /usr/src/lib/libpthread/uthread/uthread_gc.c:181
#5 0x000000004731ac78 in _thread_start ()
at /usr/src/lib/libpthread/uthread/uthread_create.c:240
#6 0x000000004731ac40 in pthread_create (thread=0x0, attr=0x0,
start_routine=0, arg=0x0)
at /usr/src/lib/libpthread/uthread/uthread_create.c:229
#1: at /usr/src/lib/libpthread/uthread/uthread_kern.c:760
760 count = _thread_sys_poll(_thread_pfd_table, nfds,
timeout_ms);
(gdb) print timeout_ms
$1 = 10009
(gdb) print nfds
$2 = 1
(gdb) print _thread_pfd_table
$3 = (struct pollfd *) 0x40e5c000
(gdb) print *_thread_pfd_table
$4 = {fd = 6, events = 64, revents = 0}
#2 is from:
/*
* There are no threads ready to run, so wait until
* something happens that changes this condition:
*/
_thread_kern_poll(1);
But this never happens because there are no more threads. Instead it
seems the code should have passed
/* There are no more threads, so exit this process: */
exit(0);
>Fix:
The poll() call in pthread library is hanging.
The garbage collector thread in
/usr/src/lib/libpthread/uthread/uthread_gc.c line 87,
/* Check if this is the last running thread: */
if (TAILQ_FIRST(&_thread_list) == curthread &&
TAILQ_NEXT(curthread, tle) == NULL)
/*
* This is the last thread, so it can exit
* now.
*/
f_done = 1;
Could it be that this line fails to fire because the GC thread
is also part of that list? At exit gdb says:
(gdb) print _thread_list
$1 = {tqh_first = 0x479d8400, tqh_last = 0x479d8030}
(gdb) print *_thread_list->tqh_first
$4 = {magic = 3499860245, name = 0x429fa050 "GC", lock = {
access_lock = 0 '\0', lock_owner = 0x0, fname = 0x0, lineno = 0},
tle = {
tqe_next = 0x479d8000, tqe_prev = 0x425f0148}, dle = {tqe_next = 0x0,
tqe_prev = 0x0}, start_routine = 0x423decc0 <_thread_gc>, arg = 0x0,
stack = 0x4f5b2500, attr = {sched_policy = 3, sched_inherit = 0,
sched_interval = 20000, prio = 15, suspend = 0, flags = 0, arg_attr
= 0x0,
cleanup_attr = 0, stackaddr_attr = 0x0, stacksize_attr = 524288,
guardsize_attr = 8192}, saved_sigcontext = {sc_onstack = 0,
__sc_mask13 = 0, sc_sp = 0, sc_pc = 0, sc_npc = 0, sc_tstate = 0,
sc_g1 = 0, sc_o0 = 0, sc_mask = 0}, _machdep = {fp = 1226265537,
pc = 1111398552, fs_fprs = 0, fs_fsr = 0, fs_regs = {
0 <repeats 32 times>}}, sig_saved = 0, cancelflags = 4,
suspended = SUSP_NO, continuation = 0, sigmask = 4294967295, sigpend = 0,
state = PS_COND_WAIT, last_active = 0, last_inactive = 0, slice_usec =
- -1,
wakeup_time = {tv_sec = 1277890581, tv_nsec = 852304037}, timeout = 0,
error = 0, joiner = 0x0, join_status = {thread = 0x0, ret = 0x0, error
= 0},
pqe = {tqe_next = 0x0, tqe_prev = 0x479d8280}, sqe = {tqe_next = 0x0,
tqe_prev = 0x479d8290}, qe = {tqe_next = 0x0, tqe_prev = 0x0}, data = {
mutex = 0x429fc500, cond = 0x429fc500, sigwait = 0x429fc500, fd =
{fd = 0,
branch = 1117766912, fname = 0x0}, fp = 0x429fc500,
poll_data = 0x429fc500, spinlock = 0x429fc500, thread = 0x429fc500},
poll_data = {nfds = 0, fds = 0x0}, interrupted = 0, closing_fd = 0,
signo = 0, sig_defer_count = 0, yield_on_sig_undefer = 0, flags = 133,
base_priority = 15, inherited_priority = 0, active_priority = 15,
priority_mutex_count = 0, rdlock_count = 0, mutexq = {tqh_first = 0x0,
tqh_last = 0x479d8700}, ret = 0x0, specific_data = 0x0,
specific_data_count = 0, cleanup = 0x0,
fname = 0x424eef78 "/usr/src/lib/libpthread/uthread/uthread_cond.c",
lineno = 432}
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org/
iEYEARECAAYFAkwrEUkACgkQkDLqNwOhpPh0dACffNJVUZvVePRaV8LWdhU64JUu
C5gAoKFgMruhF9RXmxfnuUE6DbU0xK1j
=+L4l
>Audit-Trail:
>Unformatted:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1