]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Fix SIP deadlock involving state changes.
authorJeff Peeler <jpeeler@digium.com>
Thu, 3 Feb 2011 23:49:28 +0000 (23:49 +0000)
committerJeff Peeler <jpeeler@digium.com>
Thu, 3 Feb 2011 23:49:28 +0000 (23:49 +0000)
Once again a call to pbx_builtin_getvar_helper (and pbx_builtin_setvar_helper)
has caused locking problems. Both of these functions lock the channel when
the channel argument is passed in!

In this case, the suspected problem (the backtrace makes it impossible to tell)
was the private being locked in sip_set_rtp_peer and then:
transmit_reinvite_with_sdp
 try_suggested_sip_codec
   pbx_builtin_getvar_helper
(Traced to verify that the fix was only required in 1.8 and later.)

(closes issue #18491)
Reported by: cmaj
Patches:
      chan_sip_fix_deadlocks_bug_18491.txt uploaded by cmaj (license 830)
Tested by: cmaj

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

channels/chan_sip.c

index b7c2270e4efee6eb44faf25d14afa1f1889b1f3c..9f95510db8a968a2fbf9ee700010bda44344f693 100644 (file)
@@ -27724,10 +27724,12 @@ static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *i
        if (!ast_bridged_channel(chan) && !sip_cfg.directrtpsetup)      /* We are in early state */
                return 0;
 
+       ast_channel_lock(chan);
        sip_pvt_lock(p);
        if (p->alreadygone) {
                /* If we're destroyed, don't bother */
                sip_pvt_unlock(p);
+               ast_channel_unlock(chan);
                return 0;
        }
 
@@ -27736,6 +27738,7 @@ static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *i
        */
        if (nat_active && !ast_test_flag(&p->flags[0], SIP_DIRECT_MEDIA_NAT)) {
                sip_pvt_unlock(p);
+               ast_channel_unlock(chan);
                return 0;
        }
 
@@ -27778,6 +27781,7 @@ static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *i
        /* Reset lastrtprx timer */
        p->lastrtprx = p->lastrtptx = time(NULL);
        sip_pvt_unlock(p);
+       ast_channel_unlock(chan);
        return 0;
 }