[Pkg-voip-commits] r9968 - /asterisk/branches/squeeze/debian/patches/AST-2012-010

maniac-guest at alioth.debian.org maniac-guest at alioth.debian.org
Wed Sep 19 12:35:28 UTC 2012


Author: maniac-guest
Date: Wed Sep 19 12:35:28 2012
New Revision: 9968

URL: http://svn.debian.org/wsvn/pkg-voip/?sc=1&rev=9968
Log:
working on backport AST-2012-010

Modified:
    asterisk/branches/squeeze/debian/patches/AST-2012-010

Modified: asterisk/branches/squeeze/debian/patches/AST-2012-010
URL: http://svn.debian.org/wsvn/pkg-voip/asterisk/branches/squeeze/debian/patches/AST-2012-010?rev=9968&op=diff
==============================================================================
--- asterisk/branches/squeeze/debian/patches/AST-2012-010 (original)
+++ asterisk/branches/squeeze/debian/patches/AST-2012-010 Wed Sep 19 12:35:28 2012
@@ -12,8 +12,10 @@
 
 Don't use sip_pvt_lock_full or ast_channel_unref functions.
 
---- a/channels/chan_sip.c
-+++ b/channels/chan_sip.c
+Index: asterisk-1.6.2.9/channels/chan_sip.c
+===================================================================
+--- asterisk-1.6.2.9.orig/channels/chan_sip.c	2012-09-19 12:20:49.000000000 +0200
++++ asterisk-1.6.2.9/channels/chan_sip.c	2012-09-19 14:31:28.000000000 +0200
 @@ -1662,6 +1662,7 @@
  	struct sip_auth *peerauth;		/*!< Realm authentication */
  	int noncecount;				/*!< Nonce-count */
@@ -30,7 +32,15 @@
  	int autokillid;				/*!< Auto-kill ID (scheduler) */
  	int t38id;                              /*!< T.38 Response ID */
  	enum transfermodes allowtransfer;	/*!< REFER: restriction scheme */
-@@ -4081,7 +4083,7 @@
+@@ -2392,6 +2394,7 @@
+ static int restart_monitor(void);
+ static void peer_mailboxes_to_str(struct ast_str **mailbox_str, struct sip_peer *peer);
+ static struct ast_variable *copy_vars(struct ast_variable *src);
++static struct ast_channel *sip_pvt_lock_full(struct sip_pvt *pvt);
+ /* static int sip_addrcmp(char *name, struct sockaddr_in *sin);	Support for peer matching */
+ static int sip_refer_allocate(struct sip_pvt *p);
+ static void ast_quiet_chan(struct ast_channel *chan);
+@@ -4081,7 +4084,7 @@
  			ast_debug(3, "Re-scheduled destruction of SIP call %s\n", p->callid ? p->callid : "<unknown>");
  			append_history(p, "ReliableXmit", "timeout");
  			if (sscanf(p->lastmsg, "Tx: %30s", method_str) == 1 || sscanf(p->lastmsg, "Rx: %30s", method_str) == 1) {
@@ -39,27 +49,29 @@
  					pvt_set_needdestroy(p, "autodestruct");
  				}
  			}
-@@ -6092,6 +6094,19 @@
- 	return 0;
+@@ -6093,6 +6096,21 @@
  }
+ 
  
 +static int reinvite_timeout(const void *data)
 +{
 +	struct sip_pvt *dialog = (struct sip_pvt *) data;
-+	struct ast_channel *owner = sip_pvt_lock(dialog);
++	struct ast_channel *owner = sip_pvt_lock_full(dialog);
 +	dialog->reinviteid = -1;
 +	check_pendings(dialog);
 +	if (owner) {
 +		ast_channel_unlock(owner);
++		ao2_ref(owner, -1); //ast_channel_unref(owner);
 +	}
 +	sip_pvt_unlock(dialog);
 +	dialog_unref(dialog, "unref for reinvite timeout");
 +	return 0;
 +}
- 
++
  /*! \brief  sip_hangup: Hangup SIP call
   * Part of PBX interface, called from ast_hangup */
-@@ -6289,8 +6304,16 @@
+ static int sip_hangup(struct ast_channel *ast)
+@@ -6289,8 +6307,16 @@
  				ast_set_flag(&p->flags[0], SIP_PENDINGBYE);	
  				ast_clear_flag(&p->flags[0], SIP_NEEDREINVITE);	
  				AST_SCHED_DEL_UNREF(sched, p->waitid, dialog_unref(p, "when you delete the waitid sched, you should dec the refcount for the stored dialog ptr"));
@@ -77,7 +89,7 @@
  			}
  		}
  	}
-@@ -7338,6 +7361,7 @@
+@@ -7338,6 +7364,7 @@
  	p->method = intended_method;
  	p->initid = -1;
  	p->waitid = -1;
@@ -85,7 +97,80 @@
  	p->autokillid = -1;
  	p->request_queue_sched_id = -1;
  	p->provisional_keepalive_sched_id = -1;
-@@ -10715,7 +10739,7 @@
+@@ -7513,6 +7540,72 @@
+  	return found;
+ }
+ 
++/*! \internal
++ *
++ * \brief Locks both pvt and pvt owner if owner is present.
++ *
++ * \note This function gives a ref to pvt->owner if it is present and locked.
++ *       This reference must be decremented after pvt->owner is unlocked.
++ *
++ * \note This function will never give you up,
++ * \note This function will never let you down.
++ * \note This function will run around and desert you.
++ *
++ * \pre pvt is not locked
++ * \post pvt is locked
++ * \post pvt->owner is locked and its reference count is increased (if pvt->owner is not NULL)
++ *
++ * \returns a pointer to the locked and reffed pvt->owner channel if it exists.
++ */
++static struct ast_channel *sip_pvt_lock_full(struct sip_pvt *pvt)
++{
++	struct ast_channel *chan;
++
++	/* Locking is simple when it is done right.  If you see a deadlock resulting
++	 * in this function, it is not this function's fault, Your problem exists elsewhere.
++	 * This function is perfect... seriously. */
++	for (;;) {
++		/* First, get the channel and grab a reference to it */
++		sip_pvt_lock(pvt);
++		chan = pvt->owner;
++		if (chan) {
++			/* The channel can not go away while we hold the pvt lock.
++			 * Give the channel a ref so it will not go away after we let
++			 * the pvt lock go. */
++			ao2_ref(chan, +1); //ast_channel_ref(chan);
++		} else {
++			/* no channel, return pvt locked */
++			return NULL;
++		}
++
++		/* We had to hold the pvt lock while getting a ref to the owner channel
++		 * but now we have to let this lock go in order to preserve proper
++		 * locking order when grabbing the channel lock */
++		sip_pvt_unlock(pvt);
++
++		/* Look, no deadlock avoidance, hooray! */
++		ast_channel_lock(chan);
++		sip_pvt_lock(pvt);
++
++		if (pvt->owner == chan) {
++			/* done */
++			break;
++		}
++
++		/* If the owner changed while everything was unlocked, no problem,
++		 * just start over and everthing will work.  This is rare, do not be
++		 * confused by this loop and think this it is an expensive operation.
++		 * The majority of the calls to this function will never involve multiple
++		 * executions of this loop. */
++		ast_channel_unlock(chan);
++		ao2_ref(chan, -1); //ast_channel_unref(chan);
++		sip_pvt_unlock(pvt);
++	}
++
++	/* If owner exists, it is locked and reffed */
++	return pvt->owner;
++}
++
+ /*! \brief find or create a dialog structure for an incoming SIP message.
+  * Connect incoming SIP message to current dialog or create new dialog structure
+  * Returns a reference to the sip_pvt object, remember to give it back once done.
+@@ -10715,7 +10808,7 @@
  	initialize_initreq(p, &req);
  	p->lastinvite = p->ocseq;
  	ast_set_flag(&p->flags[0], SIP_OUTGOING);       /* Change direction of this dialog */
@@ -94,7 +179,7 @@
  	return send_request(p, &req, XMIT_CRITICAL, p->ocseq);
  }
  
-@@ -17736,17 +17760,20 @@
+@@ -17736,17 +17829,20 @@
  static void check_pendings(struct sip_pvt *p)
  {
  	if (ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) {
@@ -121,7 +206,7 @@
  			/* Perhaps there is an SD change INVITE outstanding */
  			transmit_request_with_auth(p, SIP_BYE, 0, XMIT_RELIABLE, TRUE);
  		}
-@@ -17821,9 +17848,17 @@
+@@ -17821,9 +17917,17 @@
   	if (resp >= 300 && (p->invitestate == INV_CALLING || p->invitestate == INV_PROCEEDING || p->invitestate == INV_EARLY_MEDIA ))
   		p->invitestate = INV_COMPLETED;
   	




More information about the Pkg-voip-commits mailing list