Index: channels/chan_dahdi.c =================================================================== --- channels/chan_dahdi.c (revision 266141) +++ channels/chan_dahdi.c (working copy) @@ -4399,8 +4399,12 @@ /* Here we have to retain the lock on both the main channel, the 3-way channel, and the private structure -- not especially easy or clean */ while (p->subs[SUB_THREEWAY].owner && ast_mutex_trylock(&p->subs[SUB_THREEWAY].owner->lock)) { + int res; /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */ - ast_mutex_unlock(&p->lock); + if ((res = ast_mutex_unlock(&p->lock))) { + ast_log(LOG_ERROR, "chan_dahdi bug! '&p->lock' was not locked upon entry to 'dahdi_handle_dtmfup': %s\n", strerror(res)); + return NULL; + } DEADLOCK_AVOIDANCE(&ast->lock); /* We can grab ast and p in that order, without worry. We should make sure nothing seriously bad has happened though like some sort of bizarre double Index: channels/chan_h323.c =================================================================== --- channels/chan_h323.c (revision 266141) +++ channels/chan_h323.c (working copy) @@ -313,10 +313,8 @@ if (pvt) { ast_mutex_lock(&pvt->lock); /* Don't hold pvt lock while trying to lock the channel */ - while(pvt->owner && ast_channel_trylock(pvt->owner)) { - ast_mutex_unlock(&pvt->lock); - usleep(1); - ast_mutex_lock(&pvt->lock); + while (pvt->owner && ast_channel_trylock(pvt->owner)) { + DEADLOCK_AVOIDANCE(&pvt->lock); } if (pvt->owner) { Index: channels/chan_agent.c =================================================================== --- channels/chan_agent.c (revision 266141) +++ channels/chan_agent.c (working copy) @@ -707,7 +707,12 @@ ast_mutex_lock(&p->lock); if (p->chan && !ast_check_hangup(p->chan)) { while (ast_channel_trylock(p->chan)) { - ast_channel_unlock(ast); + int res; + if ((res = ast_channel_unlock(ast))) { + ast_log(LOG_ERROR, "chan_agent bug! Channel was not locked upon entry to agent_indicate: %s\n", strerror(res)); + ast_mutex_unlock(&p->lock); + return -1; + } usleep(1); ast_channel_lock(ast); } Index: channels/chan_local.c =================================================================== --- channels/chan_local.c (revision 266141) +++ channels/chan_local.c (working copy) @@ -183,10 +183,18 @@ /* Ensure that we have both channels locked */ while (other && ast_channel_trylock(other)) { - ast_mutex_unlock(&p->lock); + int res; + if ((res = ast_mutex_unlock(&p->lock))) { + ast_log(LOG_ERROR, "chan_local bug! '&p->lock' was not locked when entering local_queue_frame! (%s)\n", strerror(res)); + return -1; + } if (us && us_locked) { do { - ast_channel_unlock(us); + if (ast_channel_unlock(us)) { + ast_log(LOG_ERROR, "chan_local bug! Our channel was not locked, yet arguments indicated that it was!!\n"); + ast_mutex_lock(&p->lock); + return -1; + } usleep(1); ast_channel_lock(us); } while (ast_mutex_trylock(&p->lock)); Index: include/asterisk/lock.h =================================================================== --- include/asterisk/lock.h (revision 266141) +++ include/asterisk/lock.h (working copy) @@ -204,13 +204,21 @@ 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 __res2, __res = ast_find_lock_info(lock, __filename, sizeof(__filename), &__lineno, __func, sizeof(__func), __mutex_name, sizeof(__mutex_name)); \ + __res2 = ast_mutex_unlock(lock); \ usleep(1); \ if (__res < 0) { /* Shouldn't ever happen, but just in case... */ \ - ast_mutex_lock(lock); \ + if (__res2 == 0) { \ + ast_mutex_lock(lock); \ + } else { \ + ast_log(LOG_WARNING, "Could not unlock mutex '%s': %s and no lock info found! I will NOT try to relock.\n", #lock, strerror(__res2)); \ + } \ } else { \ - __ast_pthread_mutex_lock(__filename, __lineno, __func, __mutex_name, lock); \ + if (__res == 0) { \ + __ast_pthread_mutex_lock(__filename, __lineno, __func, __mutex_name, lock); \ + } else { \ + ast_log(LOG_WARNING, "Could not unlock mutex '%s': %s. {{{Originally locked at %s line %d: (%s) '%s'}}} I will NOT try to relock.\n", #lock, strerror(__res2), __filename, __lineno, __func, __mutex_name); \ + } \ } \ } while (0) @@ -437,6 +445,8 @@ } static inline int __ast_pthread_mutex_trylock(const char *filename, int lineno, const char *func, + const char* mutex_name, ast_mutex_t *t) __attribute__((warn_unused_result)); +static inline int __ast_pthread_mutex_trylock(const char *filename, int lineno, const char *func, const char* mutex_name, ast_mutex_t *t) { int res; @@ -716,9 +726,15 @@ #else /* !DEBUG_THREADS */ #define DEADLOCK_AVOIDANCE(lock) \ - ast_mutex_unlock(lock); \ - usleep(1); \ - ast_mutex_lock(lock); + do { \ + int __res; \ + if (!(__res = ast_mutex_unlock(lock))) { \ + usleep(1); \ + ast_mutex_lock(lock); \ + } else { \ + ast_log(LOG_WARNING, "Failed to unlock mutex '%s' (%s). I will NOT try to relock. {{{ THIS IS A BUG. }}}\n", #lock, strerror(__res)); \ + } \ + } while (0) typedef pthread_mutex_t ast_mutex_t; @@ -1371,7 +1387,7 @@ #define ast_channel_lock(x) ast_mutex_lock(&x->lock) /*! \brief Unlock a channel. If DEBUG_CHANNEL_LOCKS is defined in the Makefile, print relevant output for debugging */ -#define ast_channel_unlock(x) ast_mutex_unlock(&x->lock) +#define ast_channel_unlock(x) ast_mutex_unlock(&x->lock) /*! \brief Try locking a channel. If DEBUG_CHANNEL_LOCKS is defined in the Makefile, print relevant output for debugging */ #define ast_channel_trylock(x) ast_mutex_trylock(&x->lock) @@ -1393,7 +1409,7 @@ #define ast_channel_trylock(a) __ast_channel_trylock(a, __FILE__, __LINE__, __PRETTY_FUNCTION__) /*! \brief Lock AST channel (and print debugging output) \note You need to enable DEBUG_CHANNEL_LOCKS for this function */ -int __ast_channel_trylock(struct ast_channel *chan, const char *file, int lineno, const char *func); +int __ast_channel_trylock(struct ast_channel *chan, const char *file, int lineno, const char *func) __attribute__((warn_unused_result)); #endif #endif /* _ASTERISK_LOCK_H */