IAX2: fix race condition with nativebridge transfers.
authorAlec L Davis <sivad.a@paradise.net.nz>
Mon, 10 Jun 2013 07:35:06 +0000 (07:35 +0000)
committerAlec L Davis <sivad.a@paradise.net.nz>
Mon, 10 Jun 2013 07:35:06 +0000 (07:35 +0000)
1). When touching the bridgecallno, we need to lock it.

2). stop_stuff() which calls iax2_destroy_helper()
    Assumes the lock on the pvt is already held, when iax2_destroy_helper() is called.
    Thus we need to lock the bridgecallno pvt before we call stop_stuff(iaxs[fr->callno]->bridgecallno);

3).   When evaluating the state of 'callno->transferring' of the current leg,
    we can't change it to READY unless the bridgecallno is locked.
      Why, if we are interrupted by the other call leg before 'transferring = TRANSFER_RELEASED',
    the interrupt will find that it is READY and that the bridgecallno is also READY so Releases the legs.

(closes issue ASTERISK-21409)

Reported by: alecdavis
Tested by: alecdavis
alecdavis (license 585)

Review https://reviewboard.asterisk.org/r/2594/
........

Merged revisions 391062 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........

Merged revisions 391063 from http://svn.asterisk.org/svn/asterisk/branches/11

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@391064 65c4cc65-6c06-0410-ace0-fbb531ad65f3

channels/chan_iax2.c

index 6f1aec0..8fe51b4 100644 (file)
@@ -11215,6 +11215,15 @@ immediatedial:
                                }
                                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;
+                                       }
+                               }
+
                                if ((iaxs[fr->callno]->transferring == TRANSFER_BEGIN) ||
                                    (iaxs[fr->callno]->transferring == TRANSFER_MBEGIN)) {
                                        if (iaxs[fr->callno]->transferring == TRANSFER_MBEGIN)
@@ -11263,6 +11272,9 @@ immediatedial:
                                                }
                                        }
                                }
+                               if (iaxs[fr->callno]->bridgecallno) {
+                                       ast_mutex_unlock(&iaxsl[iaxs[fr->callno]->bridgecallno]);
+                               }
                                break;
                        case IAX_COMMAND_TXREQ:
                                try_transfer(iaxs[fr->callno], &ies);