[asterisk-bugs] [JIRA] (ASTERISK-21409) Race condition with IAX2 transfer, 2 releases happen on same call legs. locks up with many threads blocked by iax2_destroy_helper

Alec Davis (JIRA) noreply at issues.asterisk.org
Tue Jun 4 04:45:03 CDT 2013


    [ https://issues.asterisk.org/jira/browse/ASTERISK-21409?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=207007#comment-207007 ] 

Alec Davis edited comment on ASTERISK-21409 at 6/4/13 4:44 AM:
---------------------------------------------------------------

How the sequence below happens
[May 31 14:44:01] VERBOSE[30820] chan_iax2.c:     -- Channel 'IAX2/auckbdt-13262' ready to transfer
[May 31 14:44:01] VERBOSE[30824][C-00000536] chan_iax2.c:     -- Channel 'IAX2/auckbdt-20457' ready to transfer
[May 31 14:44:01] VERBOSE[30824][C-00000536] chan_iax2.c:     -- Releasing IAX2/auckbdt-20457 and IAX2/auckbdt-13262
[May 31 14:44:01] VERBOSE[30820] chan_iax2.c:     -- Releasing IAX2/auckbdt-13262 and IAX2/auckbdt-20457

this race condition happens in chan_iax.c line ~11529

{noformat}
		case IAX_COMMAND_TXREADY:
                if ((iaxs[fr->callno]->transferring == TRANSFER_BEGIN) || (iaxs[fr->callno]->transferring == TRANSFER_MBEGIN)) {
			if (iaxs[fr->callno]->transferring == TRANSFER_MBEGIN)
				iaxs[fr->callno]->transferring = TRANSFER_MREADY;
			else
				iaxs[fr->callno]->transferring = TRANSFER_READY;
			ast_verb(3, "Channel '%s' ready to transfer\n", iaxs[fr->callno]->owner ? ast_channel_name(iaxs[fr->callno]->owner) : "<Unknown>");

			/* If the other thread involved in the transfer kicks in now we'll run the following code twice */

                        if (iaxs[fr->callno]->bridgecallno) {
	                        if ((iaxs[iaxs[fr->callno]->bridgecallno]->transferring == TRANSFER_READY) || (iaxs[iaxs[fr->callno]->bridgecallno]->transferring == TRANSFER_MREADY)) {
					/* They're both ready, now release them. */
{noformat}

The example below is two IAX_COMMAND_TXREADYs are processed slightly after one another (enough time for the routine to exit), one on each leg of a call to be transferred.
The code current expects the 1st IAX_COMMAND_TXREADY to arrive, setting 'transferring' to TRANSFER_READY/MREADY and that bridged->transferring is not READY.
Then (on the bridged call leg) the 2nd IAX_COMMAND_TXREADY arrives, setting 'transferring' to TRANSFER_READY/MREADY, and bridged->transferring is already TRANSFER_READY/MREADY so then will release them.

But when the 1st IAX_COMMAND_TXREADY thread is interrupted before it's got to '->transferring = TRANSFER_MEDIA' by the 2nd IAX_COMMAND_TXREADY, things go wrong, the Releasing code gets run twice.









                
      was (Author: alecdavis):
    How the sequence below happens
[May 31 14:44:01] VERBOSE[30820] chan_iax2.c:     -- Channel 'IAX2/auckbdt-13262' ready to transfer
[May 31 14:44:01] VERBOSE[30824][C-00000536] chan_iax2.c:     -- Channel 'IAX2/auckbdt-20457' ready to transfer
[May 31 14:44:01] VERBOSE[30824][C-00000536] chan_iax2.c:     -- Releasing IAX2/auckbdt-20457 and IAX2/auckbdt-13262
[May 31 14:44:01] VERBOSE[30820] chan_iax2.c:     -- Releasing IAX2/auckbdt-13262 and IAX2/auckbdt-20457

this race condition happens in chan_iax.c line ~11529

		case IAX_COMMAND_TXREADY:
                if ((iaxs[fr->callno]->transferring == TRANSFER_BEGIN) || (iaxs[fr->callno]->transferring == TRANSFER_MBEGIN)) {
			if (iaxs[fr->callno]->transferring == TRANSFER_MBEGIN)
				iaxs[fr->callno]->transferring = TRANSFER_MREADY;
			else
				iaxs[fr->callno]->transferring = TRANSFER_READY;
			ast_verb(3, "Channel '%s' ready to transfer\n", iaxs[fr->callno]->owner ? ast_channel_name(iaxs[fr->callno]->owner) : "<Unknown>");

{color:red}*strong*			/* If the other thread involved in the transfer kicks in now we'll run the following code twice */ *strong*{color}

                        if (iaxs[fr->callno]->bridgecallno) {
	                        if ((iaxs[iaxs[fr->callno]->bridgecallno]->transferring == TRANSFER_READY) || (iaxs[iaxs[fr->callno]->bridgecallno]->transferring == TRANSFER_MREADY)) {
					/* They're both ready, now release them. */
                  
> Race condition with IAX2 transfer, 2 releases happen on same call legs. locks up with many threads blocked by iax2_destroy_helper
> ---------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: ASTERISK-21409
>                 URL: https://issues.asterisk.org/jira/browse/ASTERISK-21409
>             Project: Asterisk
>          Issue Type: Bug
>      Security Level: None
>          Components: Channels/chan_iax2
>    Affects Versions: 1.8.15.0, 11.3.0
>         Environment: Debian Squeeze
>            Reporter: Alec Davis
>         Attachments: coreshowlocks-31may.txt, full.may08.C-0000034cd.txt, gdb-31may.txt, iax-coreshowlocks-may08-auckland.txt, iax-lock-asterisk-11.txt, iax-lock-asterisk-1-8-15.txt, var_log_messages.txt
>
>
> Intermittently all IAX calls stop over the trunk.
> I think this is reproduced when a call is transferred back to the originating site, we have "transfer=on"
> Also happened with asterisk SVN-branch-11-r382514.
> Attached are the 1.8.15.0 lockup, and the 11-branch lockup.
>  

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators: https://issues.asterisk.org/jira/secure/ContactAdministrators!default.jspa
For more information on JIRA, see: http://www.atlassian.com/software/jira



More information about the asterisk-bugs mailing list