If pthread_mutex_timedlock() is not supported, apr_thread_mutex_unlock() 
will take a locked mutex and immediately lock it again:

https://github.com/apache/apr/blob/trunk/locks/unix/thread_mutex.c#L297

APR_DECLARE(apr_status_t) apr_thread_mutex_unlock(apr_thread_mutex_t *mutex)
{
    apr_status_t status;

    if (mutex->cond) {
        status = pthread_mutex_lock(&mutex->mutex);

This is undefined behaviour unless APR ensures that mutex is recursive, 
which it doesn't AFAICT.

Current versions of Coverity are smart enough to detect double-locking 
and hence this code triggers a scanner warning for every single call to 
apr_thread_mutex_unlock() within APR.

I'm not sure how to fix the problem, maybe force mutexes to be 
recursive?  But isn't it also true that all this code can be
#if'ed out for platforms which do support pthread_mutex_timedlock()?

e.g. as attached.

Regards, Joe
Index: locks/unix/thread_mutex.c
===================================================================
--- locks/unix/thread_mutex.c   (revision 1891201)
+++ locks/unix/thread_mutex.c   (working copy)
@@ -121,6 +121,7 @@
 {
     apr_status_t rv;
 
+#ifndef HAVE_PTHREAD_MUTEX_TIMEDLOCK
     if (mutex->cond) {
         apr_status_t rv2;
 
@@ -152,7 +153,8 @@
 
         return rv;
     }
-
+#endif
+    
     rv = pthread_mutex_lock(&mutex->mutex);
 #ifdef HAVE_ZOS_PTHREADS
     if (rv) {
@@ -167,6 +169,7 @@
 {
     apr_status_t rv;
 
+#ifndef HAVE_PTHREAD_MUTEX_TIMEDLOCK
     if (mutex->cond) {
         apr_status_t rv2;
 
@@ -196,7 +199,8 @@
 
         return rv;
     }
-
+#endif
+    
     rv = pthread_mutex_trylock(&mutex->mutex);
     if (rv) {
 #ifdef HAVE_ZOS_PTHREADS
@@ -298,7 +302,11 @@
 {
     apr_status_t status;
 
+#ifndef HAVE_PTHREAD_MUTEX_TIMEDLOCK
     if (mutex->cond) {
+        /* ### If the mutex is locked, and there is no guarantee this
+         * is a recursive mutex, double-locking here looks like
+         * undefined behaviour. */
         status = pthread_mutex_lock(&mutex->mutex);
         if (status) {
 #ifdef HAVE_ZOS_PTHREADS
@@ -320,6 +328,7 @@
 
         mutex->locked = 0;
     }
+#endif
 
     status = pthread_mutex_unlock(&mutex->mutex);
 #ifdef HAVE_ZOS_PTHREADS
@@ -335,9 +344,12 @@
 {
     apr_status_t rv, rv2 = APR_SUCCESS;
 
+#ifndef HAVE_PTHREAD_MUTEX_TIMEDLOCK
     if (mutex->cond) {
         rv2 = apr_thread_cond_destroy(mutex->cond);
     }
+#endif
+    
     rv = apr_pool_cleanup_run(mutex->pool, mutex, thread_mutex_cleanup);
     if (rv == APR_SUCCESS) {
         rv = rv2;
Index: include/arch/unix/apr_arch_thread_mutex.h
===================================================================
--- include/arch/unix/apr_arch_thread_mutex.h   (revision 1891201)
+++ include/arch/unix/apr_arch_thread_mutex.h   (working copy)
@@ -33,7 +33,9 @@
 struct apr_thread_mutex_t {
     apr_pool_t *pool;
     pthread_mutex_t mutex;
+#ifndef HAVE_PTHREAD_MUTEX_TIMEDLOCK
     apr_thread_cond_t *cond;
+#endif
     int locked, num_waiters;
 };
 #endif

Reply via email to