diff options
author | russell <russell@f38db490-d61c-443f-a65b-d21fe96a405b> | 2007-06-04 15:50:46 +0000 |
---|---|---|
committer | russell <russell@f38db490-d61c-443f-a65b-d21fe96a405b> | 2007-06-04 15:50:46 +0000 |
commit | 69fdc15bd774cf885cb4e08b6ac01456f084113c (patch) | |
tree | 8241756d08c19174a90ef285fdf910794873ee86 /channels | |
parent | a6c27b938f772ba52f2af7d17add49fdfa38041c (diff) |
Merged revisions 67020 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.4
........
r67020 | russell | 2007-06-04 10:47:40 -0500 (Mon, 04 Jun 2007) | 7 lines
Resolve a deadlock in chan_iax2. When handling an implicit ACK to a frame that
was marked as the final transmission for a call, don't call iax2_destroy() for
that call while the global frame queue is still locked. There is a very nice
explanation of the deadlock in the report.
(issue #9663, thorough report and patch from stevedavies, additional positive
test reports from mihai and joff_oconnell)
........
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@67022 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channels')
-rw-r--r-- | channels/chan_iax2.c | 14 |
1 files changed, 9 insertions, 5 deletions
diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c index b823c8ded..63eddf79a 100644 --- a/channels/chan_iax2.c +++ b/channels/chan_iax2.c @@ -6844,6 +6844,7 @@ static int socket_process(struct iax2_thread *thread) ((f.subclass != IAX_COMMAND_INVAL) || (f.frametype != AST_FRAME_IAX))) { unsigned char x; + int call_to_destroy; /* XXX This code is not very efficient. Surely there is a better way which still properly handles boundary conditions? XXX */ /* First we have to qualify that the ACKed value is within our window */ @@ -6857,20 +6858,23 @@ static int socket_process(struct iax2_thread *thread) /* Ack the packet with the given timestamp */ if (option_debug && iaxdebug) ast_log(LOG_DEBUG, "Cancelling transmission of packet %d\n", x); + call_to_destroy = 0; AST_LIST_LOCK(&queue); AST_LIST_TRAVERSE(&queue, cur, list) { /* If it's our call, and our timestamp, mark -1 retries */ if ((fr->callno == cur->callno) && (x == cur->oseqno)) { cur->retries = -1; /* Destroy call if this is the end */ - if (cur->final) { - if (iaxdebug && option_debug) - ast_log(LOG_DEBUG, "Really destroying %d, having been acked on final message\n", fr->callno); - iax2_destroy(fr->callno); - } + if (cur->final) + call_to_destroy = fr->callno; } } AST_LIST_UNLOCK(&queue); + if (call_to_destroy) { + if (iaxdebug && option_debug) + ast_log(LOG_DEBUG, "Really destroying %d, having been acked on final message\n", call_to_destroy); + iax2_destroy(call_to_destroy); + } } /* Note how much we've received acknowledgement for */ if (iaxs[fr->callno]) |