summaryrefslogtreecommitdiff
path: root/libpthread
diff options
context:
space:
mode:
authorLeonid Lisovskiy <lly.dev@gmail.com>2016-05-29 10:06:55 +0300
committerWaldemar Brodkorb <wbx@uclibc-ng.org>2016-05-31 21:00:13 +0200
commit361f679c652647cdea4d5a66999a4b96c1653576 (patch)
tree3c647ca4d3594e0598bc7d624a2f8ccf8ddbbfa0 /libpthread
parent8b28fc50a3891f823531aa276008e1b1b17e0a79 (diff)
linuxthreads.old: Fix segfault when pthread_mutex_unlock() called against unlocked NORMAL mutex.
Althought, it is undefined behavior, there is no reason for segfault. Program received signal SIGSEGV, Segmentation fault. __pthread_unlock (lock=lock@entry=0x804b03c <lock+16>) at libpthread/linuxthreads.old/spinlock.c:231 231 (&lock->__status, oldstatus, (long)(thr->p_nextlock) & ~1L)) It occurs only on platforms which has HAS_COMPARE_AND_SWAP defined. Restore glibc commit fbaf6e72d6 "spinlock.c (__pthread_unlock): Don't crash if called for an untaken mutex." behavior, broken later by commit 4ad1d0cfbf. Signed-off-by: Leonid Lisovskiy <lly.dev@gmail.com>
Diffstat (limited to 'libpthread')
-rw-r--r--libpthread/linuxthreads/spinlock.c12
1 files changed, 9 insertions, 3 deletions
diff --git a/libpthread/linuxthreads/spinlock.c b/libpthread/linuxthreads/spinlock.c
index 80aeda529..ce970029e 100644
--- a/libpthread/linuxthreads/spinlock.c
+++ b/libpthread/linuxthreads/spinlock.c
@@ -188,10 +188,16 @@ int __pthread_unlock(struct _pthread_fastlock * lock)
WRITE_MEMORY_BARRIER();
again:
- while ((oldstatus = lock->__status) == 1) {
- if (__compare_and_swap_with_release_semantics(&lock->__status,
+ oldstatus = lock->__status;
+ if (oldstatus == 0 || oldstatus == 1) {
+ /* No threads are waiting for this lock. Please note that we also
+ enter this case if the lock is not taken at all. If this wouldn't
+ be done here we would crash further down. */
+ if (! __compare_and_swap_with_release_semantics(&lock->__status,
oldstatus, 0))
- return 0;
+ goto again;
+
+ return 0;
}
/* Find thread in waiting queue with maximal priority */