commit cdb53a804650f08aa2c1b4badba749106197286b Author: Kamil Rytarowski Date: Thu Feb 13 16:23:21 2020 +0100 mutex: Switch the POSIX backend to PTHREAD_MUTEX_RECURSIVE The code for recursive mutexes triggered Undefined Behavior and crash as pthread_equal(3) was not used in a portable way. On the first call of mutex_lock() pthread_equal() was called with a pthread_t of value -1 which is invalid. Passing a non valid thread ID to pthread_equal is undefined. Switch the backend to native interface for POSIX recursive mutexes with PTHREAD_MUTEX_RECURSIVE and simplify the code. Detected on NetBSD/amd64 9.99.46. diff --git a/src/util/mutex.c b/src/util/mutex.c index c32bb5fd..0042e021 100644 --- a/src/util/mutex.c +++ b/src/util/mutex.c @@ -68,18 +68,16 @@ static int _mutex_destroy(MUTEX_IMPL *p) #elif defined(HAVE_PTHREAD_H) -typedef struct { - int lock_count; - pthread_t owner; - pthread_mutex_t mutex; -} MUTEX_IMPL; +typedef pthread_mutex_t MUTEX_IMPL; static int _mutex_init(MUTEX_IMPL *p) { - p->owner = (pthread_t)-1; - p->lock_count = 0; + pthread_mutexattr_t attr; - if (pthread_mutex_init(&p->mutex, NULL)) { + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + + if (pthread_mutex_init(&p->mutex, &attr)) { BD_DEBUG(DBG_BLURAY|DBG_CRIT, "pthread_mutex_init() failed !\n"); return -1; } @@ -89,39 +87,16 @@ static int _mutex_init(MUTEX_IMPL *p) static int _mutex_lock(MUTEX_IMPL *p) { - if (pthread_equal(p->owner, pthread_self())) { - /* recursive lock */ - p->lock_count++; - return 0; - } - if (pthread_mutex_lock(&p->mutex)) { BD_DEBUG(DBG_BLURAY|DBG_CRIT, "pthread_mutex_lock() failed !\n"); return -1; } - p->owner = pthread_self(); - p->lock_count = 1; - return 0; } static int _mutex_unlock(MUTEX_IMPL *p) { - if (!pthread_equal(p->owner, pthread_self())) { - BD_DEBUG(DBG_BLURAY|DBG_CRIT, "bd_mutex_unlock(): not owner !\n"); - return -1; - } - - p->lock_count--; - if (p->lock_count > 0) { - return 0; - } - - /* unlock */ - - p->owner = (pthread_t)-1; - if (pthread_mutex_unlock(&p->mutex)) { BD_DEBUG(DBG_BLURAY|DBG_CRIT, "pthread_mutex_unlock() failed !\n"); return -1; @@ -132,9 +107,6 @@ static int _mutex_unlock(MUTEX_IMPL *p) static int _mutex_destroy(MUTEX_IMPL *p) { - _mutex_lock(p); - _mutex_unlock(p); - if (pthread_mutex_destroy(&p->mutex)) { BD_DEBUG(DBG_BLURAY|DBG_CRIT, "pthread_mutex_destroy() failed !\n"); return -1; @@ -193,4 +165,3 @@ int bd_mutex_destroy(BD_MUTEX *p) X_FREE(p->impl); return 0; } -