[asterisk-commits] pjsip: Fix deadlock with suspend taskprocessor on masquerade (asterisk[13])

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Aug 10 19:19:09 CDT 2016


Anonymous Coward #1000019 has submitted this change and it was merged.

Change subject: pjsip: Fix deadlock with suspend taskprocessor on masquerade
......................................................................


pjsip: Fix deadlock with suspend taskprocessor on masquerade

If both channels which should be masqueraded
are in the same serializer:
1st channel will be locked waiting condition 'complete'
2nd channel will be locked waiting condition 'suspended'

On heavy load system a chance that both channels will be in
the same serializer 'pjsip/distibutor' is very high.

To reproduce compile res_pjsip/pjsip_distributor.c with
DISTRIBUTOR_POOL_SIZE=1

Steps to reproduce:
1. Party A calls Party B (bridged call 'AB')
2. Party B places Party A on hold
3. Party B calls Voicemail app (non-bridged call 'BV')
4. Party B attended transfers Party A to voicemail using REFER.
5. When asterisk masquerades calls 'AB' and 'BV',
   a deadlock is happened.

This patch adds a suspension indicator to the taskprocessor.
When a session suspends/unsuspends the serializer
it sets the indicator to the appropriate state.
The session checks the suspension indicator before
suspend the serializer.

ASTERISK-26145 #close

Change-Id: Iaaebee60013a58c942ba47b1b4930a63e686663b
---
M include/asterisk/taskprocessor.h
M main/taskprocessor.c
M res/res_pjsip_session.c
3 files changed, 70 insertions(+), 0 deletions(-)

Approvals:
  George Joseph: Looks good to me, approved
  Richard Mudgett: Looks good to me, but someone else must approve
  Anonymous Coward #1000019: Verified



diff --git a/include/asterisk/taskprocessor.h b/include/asterisk/taskprocessor.h
index e511222..7c79036 100644
--- a/include/asterisk/taskprocessor.h
+++ b/include/asterisk/taskprocessor.h
@@ -242,6 +242,38 @@
 	int (*task_exe)(struct ast_taskprocessor_local *local), void *datap);
 
 /*!
+ * \brief Indicate the taskprocessor is suspended.
+ *
+ * \since 13.12.0
+ *
+ * \param tps Task processor.
+ * \retval 0 success
+ * \retval -1 failure
+ */
+int ast_taskprocessor_suspend(struct ast_taskprocessor *tps);
+
+/*!
+ * \brief Indicate the taskprocessor is unsuspended.
+ *
+ * \since 13.12.0
+ *
+ * \param tps Task processor.
+ * \retval 0 success
+ * \retval -1 failure
+ */
+int ast_taskprocessor_unsuspend(struct ast_taskprocessor *tps);
+
+/*!
+ * \brief Get the task processor suspend status
+ *
+ * \since 13.12.0
+ *
+ * \param tps Task processor.
+ * \retval non-zero if the task processor is suspended
+ */
+int ast_taskprocessor_is_suspended(struct ast_taskprocessor *tps);
+
+/*!
  * \brief Pop a task off the taskprocessor and execute it.
  *
  * \since 12.0.0
diff --git a/main/taskprocessor.c b/main/taskprocessor.c
index 7ce3e4f..0c429cf 100644
--- a/main/taskprocessor.c
+++ b/main/taskprocessor.c
@@ -91,6 +91,8 @@
 	unsigned int high_water_warned:1;
 	/*! Indicates that a high water alert is active on this taskprocessor */
 	unsigned int high_water_alert:1;
+	/*! Indicates if the taskprocessor is currently suspended */
+	unsigned int suspended:1;
 };
 
 /*!
@@ -910,6 +912,33 @@
 	return taskprocessor_push(tps, tps_task_alloc_local(task_exe, datap));
 }
 
+int ast_taskprocessor_suspend(struct ast_taskprocessor *tps)
+{
+	if (tps) {
+		ao2_lock(tps);
+		tps->suspended = 1;
+		ao2_unlock(tps);
+		return 0;
+	}
+	return -1;
+}
+
+int ast_taskprocessor_unsuspend(struct ast_taskprocessor *tps)
+{
+	if (tps) {
+		ao2_lock(tps);
+		tps->suspended = 0;
+		ao2_unlock(tps);
+		return 0;
+	}
+	return -1;
+}
+
+int ast_taskprocessor_is_suspended(struct ast_taskprocessor *tps)
+{
+	return tps ? tps->suspended : -1;
+}
+
 int ast_taskprocessor_execute(struct ast_taskprocessor *tps)
 {
 	struct ast_taskprocessor_local local;
diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c
index 4290f68..a41e0aa 100644
--- a/res/res_pjsip_session.c
+++ b/res/res_pjsip_session.c
@@ -1559,6 +1559,11 @@
 		return;
 	}
 
+	if (ast_taskprocessor_is_suspended(session->serializer)) {
+		/* The serializer already suspended. */
+		return;
+	}
+
 	suspender = ao2_alloc(sizeof(*suspender), sip_session_suspender_dtor);
 	if (!suspender) {
 		/* We will just have to hope that the system does not deadlock */
@@ -1583,6 +1588,8 @@
 		ast_cond_wait(&suspender->cond_suspended, ao2_object_get_lockaddr(suspender));
 	}
 	ao2_unlock(suspender);
+
+	ast_taskprocessor_suspend(session->serializer);
 }
 
 void ast_sip_session_unsuspend(struct ast_sip_session *session)
@@ -1602,6 +1609,8 @@
 	ao2_unlock(suspender);
 
 	ao2_ref(suspender, -1);
+
+	ast_taskprocessor_unsuspend(session->serializer);
 }
 
 /*!

-- 
To view, visit https://gerrit.asterisk.org/3424
To unsubscribe, visit https://gerrit.asterisk.org/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: Iaaebee60013a58c942ba47b1b4930a63e686663b
Gerrit-PatchSet: 3
Gerrit-Project: asterisk
Gerrit-Branch: 13
Gerrit-Owner: Alexei Gradinari <alex2grad at gmail.com>
Gerrit-Reviewer: Anonymous Coward #1000019
Gerrit-Reviewer: George Joseph <gjoseph at digium.com>
Gerrit-Reviewer: Joshua Colp <jcolp at digium.com>
Gerrit-Reviewer: Richard Mudgett <rmudgett at digium.com>



More information about the asterisk-commits mailing list