From 5f01095e7e5dc5671c0c03644fbfbc9e5cc536b5 Mon Sep 17 00:00:00 2001
From: Grzegorz Sluja <grzegorz.sluja@iopsys.eu>
Date: Mon, 2 Oct 2023 12:37:44 +0000
Subject: [PATCH] Fix asterisk hang during call conference start

When the call conference is creating there are 2 threads run in parallel. Merging 2 bridges into
one and unhold indication for both channels created before conference. These things were not
synchronized what caused that sometimes asterisk was hanging because the same resources are used
for both threads. Extend locked area solve the issue.
---
 src/channels/chan_voicemngr.c | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/src/channels/chan_voicemngr.c b/src/channels/chan_voicemngr.c
index 60fb25d..30724ef 100644
--- a/src/channels/chan_voicemngr.c
+++ b/src/channels/chan_voicemngr.c
@@ -838,7 +838,6 @@ static int chan_voicemngr_indicate(struct ast_channel *ast, int condition, const
 	case AST_CONTROL_UNHOLD:
 		pvt_lock(sub->parent, "indicate");
 		chan_voicemngr_stop_dialtone(sub->parent);
-		pvt_unlock(sub->parent);
 		// Play a beep when unholding.
 		play_bridge_channel = ast_channel_get_bridge_channel(ast);
 		ast_bridge_channel_queue_playfile(play_bridge_channel, NULL, "beep", NULL);
@@ -852,6 +851,7 @@ static int chan_voicemngr_indicate(struct ast_channel *ast, int condition, const
 		astFrame.frametype = AST_FRAME_CONTROL;
 		astFrame.subclass.integer = AST_CONTROL_SRCUPDATE;
 		ast_bridge_queue_everyone_else(myBridge, NULL, &astFrame);
+		pvt_unlock(sub->parent);
 		break;
 
 	case AST_CONTROL_UPDATE_RTP_PEER:
@@ -5388,16 +5388,15 @@ static int chan_voicemngr_create_conference(struct chan_voicemngr_pvt *p)
 
 	// Move second call into first bridge and wait for it to finish.
 	chanToKick[0] = second->owner;
-        if(onholdBridge && secondBridge)
-		res = ast_bridge_merge(onholdBridge, secondBridge, 0, chanToKick, 1);
 	pvt_lock(second->parent, "moving call to first bridge");
+	if(onholdBridge && secondBridge)
+		res = ast_bridge_merge(onholdBridge, secondBridge, 0, chanToKick, 1);
 	while(ast_bridge_find_by_id(second->conference_id)) sched_yield();
-	pvt_unlock(second->parent);
         // SIP calls need unhold sent to the bridge as well.
 	astFrame.frametype = AST_FRAME_CONTROL;
 	astFrame.subclass.integer = AST_CONTROL_UNHOLD;
 	ast_bridge_queue_everyone_else(onholdBridge, NULL, &astFrame);
-
+	pvt_unlock(second->parent);
         ast_log(LOG_NOTICE,"Conference started \n");
 	return res;
 }
-- 
GitLab