summaryrefslogtreecommitdiff
path: root/main/taskprocessor.c
diff options
context:
space:
mode:
authorAlexei Gradinari <alex2grad@gmail.com>2016-08-06 11:57:08 -0400
committerAlexei Gradinari <alex2grad@gmail.com>2016-08-10 15:14:38 -0500
commit820879415f7b6dd7ea300b6b43308d8cffb7256d (patch)
tree6c3e41082f474332d571fe29d95a87b982798592 /main/taskprocessor.c
parentd78fe8fed0d0a76e11b2884a65b66e82b28a6019 (diff)
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
Diffstat (limited to 'main/taskprocessor.c')
-rw-r--r--main/taskprocessor.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/main/taskprocessor.c b/main/taskprocessor.c
index 2f0124045..4a8497f11 100644
--- a/main/taskprocessor.c
+++ b/main/taskprocessor.c
@@ -91,6 +91,8 @@ struct ast_taskprocessor {
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 @@ int ast_taskprocessor_push_local(struct ast_taskprocessor *tps, int (*task_exe)(
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;