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
This commit is contained in:
Alexei Gradinari
2016-08-06 11:57:08 -04:00
parent d78fe8fed0
commit 820879415f
3 changed files with 70 additions and 0 deletions

View File

@@ -1559,6 +1559,11 @@ void ast_sip_session_suspend(struct ast_sip_session *session)
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 @@ void ast_sip_session_suspend(struct ast_sip_session *session)
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 @@ void ast_sip_session_unsuspend(struct ast_sip_session *session)
ao2_unlock(suspender);
ao2_ref(suspender, -1);
ast_taskprocessor_unsuspend(session->serializer);
}
/*!