--- a/include/asterisk/lock.h +++ b/include/asterisk/lock.h @@ -199,20 +199,25 @@ * * used during deadlock avoidance, to preserve the original location where * a lock was originally acquired. + * + * We need to check that we successfully unlock the lock because + * there may be a circumstance where we don't own the lock, in which case + * we will acquire a lock and effectively leak locks (as it actually did). */ #define DEADLOCK_AVOIDANCE(lock) \ - do { \ + { \ char __filename[80], __func[80], __mutex_name[80]; \ int __lineno; \ int __res = ast_find_lock_info(lock, __filename, sizeof(__filename), &__lineno, __func, sizeof(__func), __mutex_name, sizeof(__mutex_name)); \ - ast_mutex_unlock(lock); \ + int lockres = ast_mutex_unlock(lock); \ usleep(1); \ - if (__res < 0) { /* Shouldn't ever happen, but just in case... */ \ + if (__res < 0 && lockres == 0) { /* Shouldn't ever happen, but just in case... */ \ ast_mutex_lock(lock); \ } else { \ - __ast_pthread_mutex_lock(__filename, __lineno, __func, __mutex_name, lock); \ + if (lockres == 0) \ + __ast_pthread_mutex_lock(__filename, __lineno, __func, __mutex_name, lock); \ } \ - } while (0) + } static void __attribute__((constructor)) init_empty_mutex(void) { @@ -715,10 +720,18 @@ #else /* !DEBUG_THREADS */ +/* We need to check that we successfully unlock the lock because +* there may be a circumstance where we don't own the lock, in which case +* we will acquire a lock and effectively leak locks (as it actually did!). +*/ + #define DEADLOCK_AVOIDANCE(lock) \ - ast_mutex_unlock(lock); \ - usleep(1); \ - ast_mutex_lock(lock); + { \ + int ret = ast_mutex_unlock(lock); \ + usleep(1); \ + if (ret == 0) \ + ast_mutex_lock(lock); \ + } typedef pthread_mutex_t ast_mutex_t;