From d91f72fd5f050db6c06497089e158b2d1dbf9586 Mon Sep 17 00:00:00 2001
From: Mark Spencer <markster@digium.com>
Date: Wed, 13 Aug 2003 17:32:44 +0000
Subject: [PATCH] Add any missing locking calls

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@1312 65c4cc65-6c06-0410-ace0-fbb531ad65f3
---
 CHANGES               |  1 +
 channel.c             |  2 ++
 channels/chan_agent.c | 47 ++++++++++++++++++++++++++++++++-----------
 channels/chan_local.c |  9 +++++++--
 4 files changed, 45 insertions(+), 14 deletions(-)

diff --git a/CHANGES b/CHANGES
index 16c88e52f4..60da7c975a 100755
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,4 @@
+ -- Add thread debugging
  -- Add optional pedantic SIP checking for Pingtel
  -- Allow extension names, include context, switch to use global vars.
  -- Allow variables in extensions.conf to reference previously defined ones
diff --git a/channel.c b/channel.c
index c393631795..81f3a66605 100755
--- a/channel.c
+++ b/channel.c
@@ -704,8 +704,10 @@ int ast_answer(struct ast_channel *chan)
 	switch(chan->_state) {
 	case AST_STATE_RINGING:
 	case AST_STATE_RING:
+		ast_mutex_lock(&chan->lock);
 		if (chan->pvt->answer)
 			res = chan->pvt->answer(chan);
+		ast_mutex_unlock(&chan->lock);
 		ast_setstate(chan, AST_STATE_UP);
 		if (chan->cdr)
 			ast_cdr_answer(chan->cdr);
diff --git a/channels/chan_agent.c b/channels/chan_agent.c
index 74155d0a80..3075643290 100755
--- a/channels/chan_agent.c
+++ b/channels/chan_agent.c
@@ -111,6 +111,23 @@ static struct agent_pvt {
 	struct agent_pvt *next;				/* Agent */
 } *agents = NULL;
 
+#define CHECK_FORMATS(ast, p) do { \
+	if (p->chan) {\
+		if (ast->nativeformats != p->chan->nativeformats) { \
+			ast_log(LOG_DEBUG, "Native formats changing from %d to %d\n", ast->nativeformats, p->chan->nativeformats); \
+			/* Native formats changed, reset things */ \
+			ast->nativeformats = p->chan->nativeformats; \
+			ast_log(LOG_DEBUG, "Resetting read to %d and write to %d\n", ast->readformat, ast->writeformat);\
+			ast_set_read_format(ast, ast->readformat); \
+			ast_set_write_format(ast, ast->writeformat); \
+		} \
+		if (p->chan->readformat != ast->pvt->rawreadformat)  \
+			ast_set_read_format(p->chan, ast->pvt->rawreadformat); \
+		if (p->chan->writeformat != ast->pvt->rawwriteformat) \
+			ast_set_write_format(p->chan, ast->pvt->rawwriteformat); \
+	} \
+} while(0)
+
 #define CLEANUP(ast, p) do { \
 	int x; \
 	if (p->chan) { \
@@ -227,8 +244,8 @@ static struct ast_frame  *agent_read(struct ast_channel *ast)
 	static struct ast_frame null_frame = { AST_FRAME_NULL, };
 	static struct ast_frame answer_frame = { AST_FRAME_CONTROL, AST_CONTROL_ANSWER };
 	ast_mutex_lock(&p->lock); 
+	CHECK_FORMATS(ast, p);
 	if (p->chan) {
-		p->chan->pvt->rawreadformat = ast->pvt->rawreadformat;
 		f = ast_read(p->chan);
 	} else
 		f = &null_frame;
@@ -243,16 +260,16 @@ static struct ast_frame  *agent_read(struct ast_channel *ast)
 	}
 	if (f && (f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_ANSWER)) {
 /* TC */
-	if (p->ackcall) {
-		if (option_verbose > 2)
-			ast_verbose(VERBOSE_PREFIX_3 "%s answered, waiting for '#' to acknowledge\n", p->chan->name);
-		/* Don't pass answer along */
-		ast_frfree(f);
-		f = &null_frame;
-        }
+		if (p->ackcall) {
+			if (option_verbose > 2)
+				ast_verbose(VERBOSE_PREFIX_3 "%s answered, waiting for '#' to acknowledge\n", p->chan->name);
+			/* Don't pass answer along */
+			ast_frfree(f);
+			f = &null_frame;
+	        }
         else {
-		p->acknowledged = 1;
-		f = &answer_frame;
+			p->acknowledged = 1;
+			f = &answer_frame;
         }
 	}
 	if (f && (f->frametype == AST_FRAME_DTMF) && (f->subclass == '#')) {
@@ -278,10 +295,16 @@ static int agent_write(struct ast_channel *ast, struct ast_frame *f)
 {
 	struct agent_pvt *p = ast->pvt->pvt;
 	int res = -1;
+	CHECK_FORMATS(ast, p);
 	ast_mutex_lock(&p->lock);
 	if (p->chan) {
-		p->chan->pvt->rawwriteformat = ast->pvt->rawwriteformat;
-		res = ast_write(p->chan, f);
+		if ((f->frametype != AST_FRAME_VOICE) ||
+			(f->subclass == p->chan->writeformat)) {
+			res = ast_write(p->chan, f);
+		} else {
+			ast_log(LOG_DEBUG, "Dropping one incompatible voice frame on '%s' to '%s'\n", ast->name, p->chan->name);
+			res = 0;
+		}
 	} else
 		res = 0;
 	CLEANUP(ast, p);
diff --git a/channels/chan_local.c b/channels/chan_local.c
index 7889d0fa30..9b60a02637 100755
--- a/channels/chan_local.c
+++ b/channels/chan_local.c
@@ -91,8 +91,13 @@ retrylock:
 	if (ast_mutex_trylock(&other->lock)) {
 		/* Failed to lock.  Release main lock and try again */
 		ast_mutex_unlock(&p->lock);
-		if (us)
-			ast_mutex_unlock(&us->lock);
+		if (us) {
+			if (ast_mutex_unlock(&us->lock)) {
+				ast_log(LOG_WARNING, "%s wasn't locked while sending %d/%d\n",
+					us->name, f->frametype, f->subclass);
+				us = NULL;
+			}
+		}
 		/* Wait just a bit */
 		usleep(1);
 		/* Only we can destroy ourselves, so we can't disappear here */
-- 
GitLab