From bdb0121769a47b1e8e2f043679746dc017e7068b Mon Sep 17 00:00:00 2001 From: Richard Mudgett Date: Thu, 5 Sep 2013 17:17:53 +0000 Subject: chan_iax2: Fix bridgecallno deadlock avoidance. * Fix bridgecallno deadlock avoidance. When doing deadlock avoidance, you need to retest the status of values for each loop to see if you still need the lock for bridgecallno. * As a safety check, after acquiring the bridgecallno lock you should check if iaxs[bridgecallno] is NULL just like the current callno checks. * Move setting thread->iostate to IAX_IOSTATE_IDLE to after processing any deferred frames to ensure that the iostate is IDLE when it is placed back into the idle list. defer_full_frame() tries to ensure iax2_process_thread() wakes up to process the frame. ........ Merged revisions 398379 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ Merged revisions 398380 from http://svn.asterisk.org/svn/asterisk/branches/11 ........ Merged revisions 398381 from http://svn.asterisk.org/svn/asterisk/branches/12 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@398384 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- channels/chan_iax2.c | 55 +++++++++++++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 26 deletions(-) (limited to 'channels/chan_iax2.c') diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c index 1984fc798..3069bc9bb 100644 --- a/channels/chan_iax2.c +++ b/channels/chan_iax2.c @@ -831,7 +831,7 @@ struct chan_iax2_pvt { /*! Status of knowledge of peer ADSI capability */ int peeradsicpe; - /*! Who we are bridged to */ + /*! Callno of native bridge peer. (Valid if nonzero) */ unsigned short bridgecallno; int pingid; /*!< Transmit PING request */ @@ -11221,13 +11221,13 @@ immediatedial: } break; case IAX_COMMAND_TXREJ: - if (iaxs[fr->callno]->bridgecallno) { - while (ast_mutex_trylock(&iaxsl[iaxs[fr->callno]->bridgecallno])) { - DEADLOCK_AVOIDANCE(&iaxsl[fr->callno]); - } - if (!iaxs[fr->callno]) { - break; - } + while (iaxs[fr->callno] + && iaxs[fr->callno]->bridgecallno + && ast_mutex_trylock(&iaxsl[iaxs[fr->callno]->bridgecallno])) { + DEADLOCK_AVOIDANCE(&iaxsl[fr->callno]); + } + if (!iaxs[fr->callno]) { + break; } iaxs[fr->callno]->transferring = TRANSFER_NONE; @@ -11238,20 +11238,21 @@ immediatedial: break; } - if (iaxs[iaxs[fr->callno]->bridgecallno]->transferring) { + if (iaxs[iaxs[fr->callno]->bridgecallno] + && iaxs[iaxs[fr->callno]->bridgecallno]->transferring) { iaxs[iaxs[fr->callno]->bridgecallno]->transferring = TRANSFER_NONE; send_command(iaxs[iaxs[fr->callno]->bridgecallno], AST_FRAME_IAX, IAX_COMMAND_TXREJ, 0, NULL, 0, -1); } ast_mutex_unlock(&iaxsl[iaxs[fr->callno]->bridgecallno]); break; case IAX_COMMAND_TXREADY: - if (iaxs[fr->callno]->bridgecallno) { - while (ast_mutex_trylock(&iaxsl[iaxs[fr->callno]->bridgecallno])) { - DEADLOCK_AVOIDANCE(&iaxsl[fr->callno]); - } - if (!iaxs[fr->callno]) { - break; - } + while (iaxs[fr->callno] + && iaxs[fr->callno]->bridgecallno + && ast_mutex_trylock(&iaxsl[iaxs[fr->callno]->bridgecallno])) { + DEADLOCK_AVOIDANCE(&iaxsl[fr->callno]); + } + if (!iaxs[fr->callno]) { + break; } if (iaxs[fr->callno]->transferring == TRANSFER_BEGIN) { @@ -11270,8 +11271,9 @@ immediatedial: break; } - if (!(iaxs[iaxs[fr->callno]->bridgecallno]->transferring == TRANSFER_READY) && - !(iaxs[iaxs[fr->callno]->bridgecallno]->transferring == TRANSFER_MREADY)) { + if (!iaxs[iaxs[fr->callno]->bridgecallno] + || (iaxs[iaxs[fr->callno]->bridgecallno]->transferring != TRANSFER_READY + && iaxs[iaxs[fr->callno]->bridgecallno]->transferring != TRANSFER_MREADY)) { ast_mutex_unlock(&iaxsl[iaxs[fr->callno]->bridgecallno]); break; } @@ -11655,11 +11657,10 @@ static void *iax2_process_thread(void *data) break; } - if (thread->iostate == IAX_IOSTATE_IDLE) - continue; - /* See what we need to do */ switch (thread->iostate) { + case IAX_IOSTATE_IDLE: + continue; case IAX_IOSTATE_READY: thread->actions++; thread->iostate = IAX_IOSTATE_PROCESSING; @@ -11672,14 +11673,10 @@ static void *iax2_process_thread(void *data) #ifdef SCHED_MULTITHREADED thread->schedfunc(thread->scheddata); #endif + break; default: break; } - time(&thread->checktime); - thread->iostate = IAX_IOSTATE_IDLE; -#ifdef DEBUG_SCHED_MULTITHREAD - thread->curfunc[0]='\0'; -#endif /* The network thread added us to the active_thread list when we were given * frames to process, Now that we are done, we must remove ourselves from @@ -11690,6 +11687,12 @@ static void *iax2_process_thread(void *data) /* Make sure another frame didn't sneak in there after we thought we were done. */ handle_deferred_full_frames(thread); + + time(&thread->checktime); + thread->iostate = IAX_IOSTATE_IDLE; +#ifdef DEBUG_SCHED_MULTITHREAD + thread->curfunc[0]='\0'; +#endif } /*! -- cgit v1.2.3