]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Recorded merge of revisions 199588 via svnmerge from
authorMark Michelson <mmichelson@digium.com>
Mon, 8 Jun 2009 17:35:58 +0000 (17:35 +0000)
committerMark Michelson <mmichelson@digium.com>
Mon, 8 Jun 2009 17:35:58 +0000 (17:35 +0000)
https://origsvn.digium.com/svn/asterisk/trunk

........
  r199588 | mmichelson | 2009-06-08 12:32:04 -0500 (Mon, 08 Jun 2009) | 9 lines

  Fix a deadlock that could occur when setting rtp stats on SIP calls.

  (closes issue #15143)
  Reported by: cristiandimache
  Patches:
        15143.patch uploaded by mmichelson (license 60)
  Tested by: cristiandimache
........

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

channels/chan_sip.c

index 3ba459e0eb98163f59a63580eec78a55b567ff34..0e34997d5d087c4f927623c6fff9f7d7a7ea08ba 100644 (file)
@@ -5302,6 +5302,21 @@ static int sip_hangup(struct ast_channel *ast)
                                char *videoqos = "";
                                char *textqos = "";
 
+                               /* We need to get the lock on bridge because ast_rtp_set_vars will attempt
+                                * to lock the bridge. This may get hairy...
+                                */
+                               while (bridge && ast_channel_trylock(bridge)) {
+                                       struct ast_channel *chan = p->owner;
+                                       sip_pvt_unlock(p);
+                                       do {
+                                               /* Use chan since p->owner could go NULL on us
+                                                * while p is unlocked
+                                                */
+                                               CHANNEL_DEADLOCK_AVOIDANCE(chan);
+                                       } while (sip_pvt_trylock(p));
+                                       bridge = p->owner ? ast_bridged_channel(p->owner) : NULL;
+                               }
+
                                if (p->rtp)
                                        ast_rtp_set_vars(oldowner, p->rtp);
 
@@ -5310,6 +5325,7 @@ static int sip_hangup(struct ast_channel *ast)
 
                                        if (IS_SIP_TECH(bridge->tech) && q && q->rtp)
                                                ast_rtp_set_vars(bridge, q->rtp);
+                                       ast_channel_unlock(bridge);
                                }
 
                                if (p->vrtp)
@@ -19263,6 +19279,20 @@ static int handle_request_bye(struct sip_pvt *p, struct sip_request *req)
                struct ast_channel *bridge = p->owner ? ast_bridged_channel(p->owner) : NULL;
                char *videoqos, *textqos;
 
+               /* We need to get the lock on bridge because ast_rtp_set_vars will attempt
+                * to lock the bridge. This may get hairy...
+                */
+               while (bridge && ast_channel_trylock(bridge)) {
+                       ast_channel_unlock(p->owner);
+                       do {
+                               /* Can't use DEADLOCK_AVOIDANCE since p is an ao2 object */
+                               sip_pvt_unlock(p);
+                               usleep(1);
+                               sip_pvt_lock(p);
+                       } while (p->owner && ast_channel_trylock(p->owner));
+                       bridge = p->owner ? ast_bridged_channel(p->owner) : NULL;
+               }
+
                if (p->rtp) {   
                        if (p->do_history) {
                                char *audioqos,
@@ -19291,6 +19321,7 @@ static int handle_request_bye(struct sip_pvt *p, struct sip_request *req)
 
                        if (IS_SIP_TECH(bridge->tech) && q && q->rtp)
                                ast_rtp_set_vars(bridge, q->rtp);
+                       ast_channel_unlock(bridge);
                }
 
                if (p->vrtp) {