aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrmudgett <rmudgett@f38db490-d61c-443f-a65b-d21fe96a405b>2010-09-28 01:10:25 +0000
committerrmudgett <rmudgett@f38db490-d61c-443f-a65b-d21fe96a405b>2010-09-28 01:10:25 +0000
commite2cfdefadbfd7789c6fa38cc053554a46f1e26ae (patch)
treeae2f2cb12cec0243626922c72e846b02c0aca4c4
parent13cb2d353be73d03b5da57e438e74bad3fc63c20 (diff)
Merged revisions 289057 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.8 ........ r289057 | rmudgett | 2010-09-27 20:04:37 -0500 (Mon, 27 Sep 2010) | 5 lines Avoid deadlock processing incoming AOC-E messages. Deadlock avoidance for the owner channel was not done when processing incoming AOC-E messages. ........ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@289058 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r--channels/sig_pri.c27
1 files changed, 20 insertions, 7 deletions
diff --git a/channels/sig_pri.c b/channels/sig_pri.c
index 251e6a04a..9f3ebb7be 100644
--- a/channels/sig_pri.c
+++ b/channels/sig_pri.c
@@ -3256,20 +3256,29 @@ static void sig_pri_aoc_e_from_ast(struct sig_pri_chan *pvt, struct ast_aoc_deco
* \brief send an AOC-E termination request on ast_channel and set
* hangup delay.
*
- * \param sig_pri_chan private
+ * \param pri sig_pri PRI control structure.
+ * \param chanpos Channel position in the span.
* \param ms to delay hangup
*
- * \note assumes pvt is locked
+ * \note Assumes the pri->lock is already obtained.
+ * \note Assumes the sig_pri_lock_private(pri->pvts[chanpos]) is already obtained.
*
* \return Nothing
*/
-static void sig_pri_send_aoce_termination_request(struct sig_pri_chan *pvt, unsigned int ms)
+static void sig_pri_send_aoce_termination_request(struct sig_pri_span *pri, int chanpos, unsigned int ms)
{
+ struct sig_pri_chan *pvt;
struct ast_aoc_decoded *decoded = NULL;
struct ast_aoc_encoded *encoded = NULL;
size_t encoded_size;
struct timeval whentohangup = { 0, };
+ sig_pri_lock_owner(pri, chanpos);
+ pvt = pri->pvts[chanpos];
+ if (!pvt->owner) {
+ return;
+ }
+
if (!(decoded = ast_aoc_create(AST_AOC_REQUEST, 0, AST_AOC_REQUEST_E))) {
ast_softhangup_nolock(pvt->owner, AST_SOFTHANGUP_DEV);
goto cleanup_termination_request;
@@ -3296,6 +3305,7 @@ static void sig_pri_send_aoce_termination_request(struct sig_pri_chan *pvt, unsi
ast_log(LOG_DEBUG, "Delaying hangup on %s for aoc-e msg\n", pvt->owner->name);
cleanup_termination_request:
+ ast_channel_unlock(pvt->owner);
ast_aoc_destroy_decoded(decoded);
ast_aoc_destroy_encoded(encoded);
}
@@ -5257,7 +5267,7 @@ static void *pri_dchannel(void *vpri)
if (detect_aoc_e_subcmd(e->hangup.subcmds)) {
/* If a AOC-E msg was sent during the release, we must use a
* AST_CONTROL_HANGUP frame to guarantee that frame gets read before hangup */
- ast_queue_control(pri->pvts[chanpos]->owner, AST_CONTROL_HANGUP);
+ pri_queue_control(pri, chanpos, AST_CONTROL_HANGUP);
} else {
pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
}
@@ -5395,12 +5405,15 @@ static void *pri_dchannel(void *vpri)
if (do_hangup) {
#if defined(HAVE_PRI_AOC_EVENTS)
- if (!pri->pvts[chanpos]->holding_aoce && pri->aoce_delayhangup && ast_bridged_channel(pri->pvts[chanpos]->owner)) {
- sig_pri_send_aoce_termination_request(pri->pvts[chanpos], pri_get_timer(pri->pri, PRI_TIMER_T305) / 2);
+ if (!pri->pvts[chanpos]->holding_aoce
+ && pri->aoce_delayhangup
+ && ast_bridged_channel(pri->pvts[chanpos]->owner)) {
+ sig_pri_send_aoce_termination_request(pri, chanpos,
+ pri_get_timer(pri->pri, PRI_TIMER_T305) / 2);
} else if (detect_aoc_e_subcmd(e->hangup.subcmds)) {
/* If a AOC-E msg was sent during the Disconnect, we must use a AST_CONTROL_HANGUP frame
* to guarantee that frame gets read before hangup */
- ast_queue_control(pri->pvts[chanpos]->owner, AST_CONTROL_HANGUP);
+ pri_queue_control(pri, chanpos, AST_CONTROL_HANGUP);
} else {
pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
}