diff options
author | Richard Mudgett <rmudgett@digium.com> | 2011-04-01 23:17:05 +0000 |
---|---|---|
committer | Richard Mudgett <rmudgett@digium.com> | 2011-04-01 23:17:05 +0000 |
commit | 6826b083ec4602637e367e41944946580888a1ee (patch) | |
tree | 853789c3f25f97f8a017e97cf986aaa720178e67 /channels | |
parent | 75594e6e4aee1e0b8abaa4e668ba15ac5c34eb86 (diff) |
Merged revisions 312509 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.8
........
r312509 | rmudgett | 2011-04-01 18:15:42 -0500 (Fri, 01 Apr 2011) | 22 lines
When a call going out an NT-PTMP port gets rejected, Asterisk crashes.
If a call is sent to an ISDN phone that rejects the call with
RELEASE_COMPLETE(cause: call reject(21), or busy(17)) Asterisk crashes.
I could not get my setup to crash. However, I could see the possibility
from a race condition between queuing an AST_CONTROL_BUSY to the core and
then queueing an AST_CONTROL_HANGUP. If the AST_CONTROL_BUSY is processed
before the AST_CONTROL_HANGUP is queued, the ast_channel could be
destroyed out from under chan_misdn.
Avoid this particular crash scenario by not queueing the
AST_CONTROL_HANGUP if the AST_CONTROL_BUSY was queued.
(closes issue #18408)
Reported by: wimpy
Patches:
issue18408_v1.8.patch uploaded by rmudgett (license 664)
Tested by: rmudgett, wimpy
JIRA SWP-2679
........
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@312510 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'channels')
-rw-r--r-- | channels/chan_misdn.c | 37 |
1 files changed, 22 insertions, 15 deletions
diff --git a/channels/chan_misdn.c b/channels/chan_misdn.c index 194229723..d6e10aebe 100644 --- a/channels/chan_misdn.c +++ b/channels/chan_misdn.c @@ -681,7 +681,7 @@ static ast_mutex_t cl_te_lock; static enum event_response_e cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data); -static void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel*bc, struct chan_list *ch); +static int send_cause2ast(struct ast_channel *ast, struct misdn_bchannel *bc, struct chan_list *ch); static void cl_queue_chan(struct chan_list *chan); @@ -8364,8 +8364,7 @@ static void hangup_chan(struct chan_list *ch, struct misdn_bchannel *bc) cb_log(2, port, " --> hangup\n"); ch->need_hangup = 0; ch->need_queue_hangup = 0; - if (ch->ast) { - send_cause2ast(ch->ast, bc, ch); + if (ch->ast && send_cause2ast(ch->ast, bc, ch)) { ast_hangup(ch->ast); } return; @@ -8373,13 +8372,15 @@ static void hangup_chan(struct chan_list *ch, struct misdn_bchannel *bc) if (!ch->need_queue_hangup) { cb_log(2, port, " --> No need to queue hangup\n"); + return; } ch->need_queue_hangup = 0; if (ch->ast) { - send_cause2ast(ch->ast, bc, ch); - ast_queue_hangup_with_cause(ch->ast, bc->cause); - cb_log(2, port, " --> queue_hangup\n"); + if (send_cause2ast(ch->ast, bc, ch)) { + ast_queue_hangup_with_cause(ch->ast, bc->cause); + cb_log(2, port, " --> queue_hangup\n"); + } } else { cb_log(1, port, "Cannot hangup chan, no ast\n"); } @@ -8653,26 +8654,31 @@ static void do_immediate_setup(struct misdn_bchannel *bc, struct chan_list *ch, } } +/*! + * \retval -1 if can hangup after calling. + * \retval 0 if cannot hangup after calling. + */ +static int send_cause2ast(struct ast_channel *ast, struct misdn_bchannel *bc, struct chan_list *ch) +{ + int can_hangup; - -static void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel *bc, struct chan_list *ch) { if (!ast) { chan_misdn_log(1, 0, "send_cause2ast: No Ast\n"); - return; + return 0; } if (!bc) { chan_misdn_log(1, 0, "send_cause2ast: No BC\n"); - return; + return 0; } if (!ch) { chan_misdn_log(1, 0, "send_cause2ast: No Ch\n"); - return; + return 0; } ast->hangupcause = bc->cause; + can_hangup = -1; switch (bc->cause) { - case AST_CAUSE_UNALLOCATED: case AST_CAUSE_NO_ROUTE_TRANSIT_NET: case AST_CAUSE_NO_ROUTE_DESTINATION: @@ -8699,15 +8705,16 @@ static void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel *bc, s chan_misdn_log(1, bc ? bc->port : 0, "Queued busy already\n"); break; } + ch->need_busy = 0; chan_misdn_log(1, bc ? bc->port : 0, " --> * SEND: Queue Busy pid:%d\n", bc ? bc->pid : -1); - ast_queue_control(ast, AST_CONTROL_BUSY); - ch->need_busy = 0; - + /* The BUSY is likely to cause a hangup or the user needs to hear it. */ + can_hangup = 0; break; } + return can_hangup; } |