aboutsummaryrefslogtreecommitdiffstats
path: root/channel.c
diff options
context:
space:
mode:
authorfile <file@f38db490-d61c-443f-a65b-d21fe96a405b>2007-06-11 14:29:58 +0000
committerfile <file@f38db490-d61c-443f-a65b-d21fe96a405b>2007-06-11 14:29:58 +0000
commitde3ad8cac3edf96a86ade3d678fbbac26a600d8f (patch)
tree6507c371ca1e390fd565e83b5fd1fc5917d6a4e1 /channel.c
parentadcaa229ccbc58b7334cd600be41279e48d72f66 (diff)
Improve deadlock handling of the channel list. (issue #8376 reported by one47)
git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.2@68682 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channel.c')
-rw-r--r--channel.c24
1 files changed, 17 insertions, 7 deletions
diff --git a/channel.c b/channel.c
index 5a520db43..c76c9b7e7 100644
--- a/channel.c
+++ b/channel.c
@@ -771,19 +771,29 @@ static struct ast_channel *channel_find_locked(const struct ast_channel *prev,
/* exit if chan not found or mutex acquired successfully */
done = (c == NULL) || (ast_mutex_trylock(&c->lock) == 0);
/* this is slightly unsafe, as we _should_ hold the lock to access c->name */
- if (!done && c)
+ if (!done && c) {
ast_log(LOG_DEBUG, "Avoiding %s for '%s'\n", msg, c->name);
+ if (retries == 9) {
+ /* We are about to fail due to a deadlock, so report this
+ * while we still have the list lock.
+ */
+ ast_log(LOG_WARNING, "Avoided %s for '%p', %d retries!\n", msg, c, retries);
+ /* As we have deadlocked, we will skip this channel and see if
+ * there is another match.
+ * NOTE: No point doing this for a full-name match, as there
+ * can be no more matches.
+ */
+ if (!(name && !namelen)) {
+ prev = c;
+ retries = -1;
+ }
+ }
+ }
ast_mutex_unlock(&chlock);
if (done)
return c;
usleep(1);
}
- /*
- * c is surely not null, but we don't have the lock so cannot
- * access c->name
- */
- ast_log(LOG_WARNING, "Avoided %s for '%p', %d retries!\n",
- msg, c, retries);
return NULL;
}