From 30910d48bc2f839105e08acf04463e53929ed38a Mon Sep 17 00:00:00 2001
From: Mark Spencer <markster@digium.com>
Date: Tue, 29 Jun 2004 10:51:00 +0000
Subject: [PATCH] Avoid potential deadlocks in channel_walk_locked, and detect
 serious failures

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@3340 65c4cc65-6c06-0410-ace0-fbb531ad65f3
---
 channel.c | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/channel.c b/channel.c
index 8738777057..510e0c0d12 100755
--- a/channel.c
+++ b/channel.c
@@ -452,6 +452,8 @@ struct ast_channel *ast_channel_walk_locked(struct ast_channel *prev)
 {
 	/* Returns next channel (locked) */
 	struct ast_channel *l, *ret=NULL;
+	int retries = 0;	
+retry:
 	ast_mutex_lock(&chlock);
 	l = channels;
 	if (!prev) {
@@ -465,8 +467,21 @@ struct ast_channel *ast_channel_walk_locked(struct ast_channel *prev)
 			ret = l->next;
 		l = l->next;
 	}
-	if (ret)
-		ast_mutex_lock(&ret->lock);
+	if (ret) {
+		if (ast_mutex_trylock(&ret->lock)) {
+			if (retries < 10)
+				ast_log(LOG_DEBUG, "Avoiding deadlock for '%s'\n", ret->name);
+			else
+				ast_log(LOG_WARNING, "Avoided deadlock for '%s', %d retries!\n", ret->name, retries);
+			ast_mutex_unlock(&chlock);
+			if (retries < 10) {
+				usleep(1);
+				retries++;
+				goto retry;
+			} else
+				return NULL;
+		}
+	}
 	ast_mutex_unlock(&chlock);
 	return ret;
 	
-- 
GitLab