Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 24 Jan 2017 17:30:13 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r312701 - stable/10/libexec/rtld-elf
Message-ID:  <201701241730.v0OHUD4u026294@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Tue Jan 24 17:30:13 2017
New Revision: 312701
URL: https://svnweb.freebsd.org/changeset/base/312701

Log:
  MFC r311886:
  Fix acquisition of nested write compat rtld locks.
  
  PR:	215826

Modified:
  stable/10/libexec/rtld-elf/rtld_lock.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/libexec/rtld-elf/rtld_lock.c
==============================================================================
--- stable/10/libexec/rtld-elf/rtld_lock.c	Tue Jan 24 16:47:06 2017	(r312700)
+++ stable/10/libexec/rtld-elf/rtld_lock.c	Tue Jan 24 17:30:13 2017	(r312701)
@@ -64,7 +64,7 @@ typedef struct Struct_Lock {
 } Lock;
 
 static sigset_t fullsigmask, oldsigmask;
-static int thread_flag;
+static int thread_flag, wnested;
 
 static void *
 def_lock_create(void)
@@ -117,29 +117,34 @@ def_rlock_acquire(void *lock)
 static void
 def_wlock_acquire(void *lock)
 {
-    Lock *l = (Lock *)lock;
-    sigset_t tmp_oldsigmask;
+	Lock *l;
+	sigset_t tmp_oldsigmask;
 
-    for ( ; ; ) {
-	sigprocmask(SIG_BLOCK, &fullsigmask, &tmp_oldsigmask);
-	if (atomic_cmpset_acq_int(&l->lock, 0, WAFLAG))
-	    break;
-	sigprocmask(SIG_SETMASK, &tmp_oldsigmask, NULL);
-    }
-    oldsigmask = tmp_oldsigmask;
+	l = (Lock *)lock;
+	for (;;) {
+		sigprocmask(SIG_BLOCK, &fullsigmask, &tmp_oldsigmask);
+		if (atomic_cmpset_acq_int(&l->lock, 0, WAFLAG))
+			break;
+		sigprocmask(SIG_SETMASK, &tmp_oldsigmask, NULL);
+	}
+	if (atomic_fetchadd_int(&wnested, 1) == 0)
+		oldsigmask = tmp_oldsigmask;
 }
 
 static void
 def_lock_release(void *lock)
 {
-    Lock *l = (Lock *)lock;
+	Lock *l;
 
-    if ((l->lock & WAFLAG) == 0)
-    	atomic_add_rel_int(&l->lock, -RC_INCR);
-    else {
-    	atomic_add_rel_int(&l->lock, -WAFLAG);
-    	sigprocmask(SIG_SETMASK, &oldsigmask, NULL);
-    }
+	l = (Lock *)lock;
+	if ((l->lock & WAFLAG) == 0)
+		atomic_add_rel_int(&l->lock, -RC_INCR);
+	else {
+		assert(wnested > 0);
+		atomic_add_rel_int(&l->lock, -WAFLAG);
+		if (atomic_fetchadd_int(&wnested, -1) == 1)
+			sigprocmask(SIG_SETMASK, &oldsigmask, NULL);
+	}
 }
 
 static int
@@ -373,12 +378,12 @@ _rtld_atfork_pre(int *locks)
 		return;
 
 	/*
-	 * Warning: this does not work with the rtld compat locks
-	 * above, since the thread signal mask is corrupted (set to
-	 * all signals blocked) if two locks are taken in write mode.
-	 * The caller of the _rtld_atfork_pre() must provide the
-	 * working implementation of the locks, and libthr locks are
-	 * fine.
+	 * Warning: this did not worked well with the rtld compat
+	 * locks above, when the thread signal mask was corrupted (set
+	 * to all signals blocked) if two locks were taken
+	 * simultaneously in the write mode.  The caller of the
+	 * _rtld_atfork_pre() must provide the working implementation
+	 * of the locks anyway, and libthr locks are fine.
 	 */
 	wlock_acquire(rtld_phdr_lock, &ls[0]);
 	wlock_acquire(rtld_bind_lock, &ls[1]);



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