Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 01 Sep 2008 16:10:17 +0800
From:      David Xu <davidxu@freebsd.org>
To:        Kostik Belousov <kostikbel@gmail.com>
Cc:        Daniel Eischen <deischen@freebsd.org>, Andriy Gapon <avg@icyb.net.ua>, freebsd-threads@freebsd.org
Subject:   Re: mysterious hang in pthread_create
Message-ID:  <48BBA369.9010108@freebsd.org>
In-Reply-To: <20080830184512.GH2038@deviant.kiev.zoral.com.ua>
References:  <48B7101E.7060203@icyb.net.ua> <48B71BA6.5040504@icyb.net.ua> <20080829141043.GX2038@deviant.kiev.zoral.com.ua> <48B8052A.6070908@icyb.net.ua> <20080829143645.GY2038@deviant.kiev.zoral.com.ua> <Pine.GSO.4.64.0808291223240.5086@sea.ntplx.net> <20080829190506.GA2038@deviant.kiev.zoral.com.ua> <Pine.GSO.4.64.0808301128410.9898@sea.ntplx.net> <20080830155622.GF2038@deviant.kiev.zoral.com.ua> <Pine.GSO.4.64.0808301200460.9898@sea.ntplx.net> <20080830184512.GH2038@deviant.kiev.zoral.com.ua>

next in thread | previous in thread | raw e-mail | index | archive | help
Kostik Belousov wrote:
> Ok, let me to tell the whole story. I am sure that in fact you know
> it better then me.
> 
> Assuming libthr is the only threading library, there are two locking
> implementations for the rtld: 'default' and the one supplied by libthr.
> On the first call to pthread_create(), libthr calls _rtld_thread_init()
> to substitute the default by the implementation from libthr.
> 
> In fact, default implementation is broken from my point of view. For
> instance, thread_flag update is not atomic. Moreover, it does not
> correctly handles sequential acquision of several locks, due
> to thread_flag.
> 
> The dl_iterate_phdr() function, called by gcc exception handling support
> code, does exactly this. It acquires rtld_phdr_lock, then rtld_bind_lock.
> [I shall admit it does this after my change]. In particular, this would
> leave the bit for the bind lock set in the thread_flag.
> 
> Andriy' example throw the exception and calls dl_iterate_phdr() before
> first thread is created. On thread creation, _rtld_thread_init() is
> called, that tries to move the locks according to thread_flag. This is
> the cause for the reported wlock acquisition.
> 
> I do not want to change anything in the default rtld locking. It is
> disfunctional from the time libc_r is gone, and I think it would be
> better to make it nop. My change makes the image that is linked with
> libthr, to consistently use libthr locks.

The ancient bug is in rtld, rlock_acquire() and wlock_acquire() test
thread_flag as a boolean value, because pt_iterate_phdr() tries to
lock two locks at same time, this test will always fail once it
acquired first lock.

The following silly patch fixes the problem Andriy encountered:

Index: rtld_lock.c
===================================================================
--- rtld_lock.c	(版本 182594)
+++ rtld_lock.c	(工作副本)
@@ -184,7 +184,7 @@
  int
  rlock_acquire(rtld_lock_t lock)
  {
-	if (thread_mask_set(lock->mask)) {
+	if (thread_mask_set(lock->mask) & lock->mask) {
  	    dbg("rlock_acquire: recursed");
  	    return (0);
  	}
@@ -195,7 +195,7 @@
  int
  wlock_acquire(rtld_lock_t lock)
  {
-	if (thread_mask_set(lock->mask)) {
+	if (thread_mask_set(lock->mask) & lock->mask) {
  	    dbg("wlock_acquire: recursed");
  	    return (0);
  	}


Regards,
David Xu




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?48BBA369.9010108>