[asterisk-commits] schmidts: branch schmidts/unleash-the-beast r343849 - /team/schmidts/unleash-...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Nov 8 08:58:00 CST 2011


Author: schmidts
Date: Tue Nov  8 08:57:53 2011
New Revision: 343849

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=343849
Log:
Backport for 1.8 from the fix deadlock between subscription event RWLOCK and dialogs container lock in chan_sip.c

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


Modified:
    team/schmidts/unleash-the-beast/channels/chan_sip.c

Modified: team/schmidts/unleash-the-beast/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/team/schmidts/unleash-the-beast/channels/chan_sip.c?view=diff&rev=343849&r1=343848&r2=343849
==============================================================================
--- team/schmidts/unleash-the-beast/channels/chan_sip.c (original)
+++ team/schmidts/unleash-the-beast/channels/chan_sip.c Tue Nov  8 08:57:53 2011
@@ -1335,7 +1335,7 @@
 static struct sip_auth *find_realm_authentication(struct sip_auth_container *credentials, const char *realm);
 
 /*--- Misc functions */
-static void check_rtp_timeout(struct sip_pvt *dialog, time_t t);
+static int check_rtp_timeout(struct sip_pvt *dialog, time_t t);
 static int reload_config(enum channelreloadreason reason);
 static void add_diversion_header(struct sip_request *req, struct sip_pvt *pvt);
 static int expire_register(const void *data);
@@ -2940,16 +2940,6 @@
 }
 
  /*!
- * \brief Unlink a dialog from the dialogs_checkrtp container
- */
-static void *dialog_unlink_rtpcheck(struct sip_pvt *dialog)
-{
-	ao2_t_unlink(dialogs_rtpcheck, dialog, "unlinking dialog_rtpcheck via ao2_unlink");
-	return NULL;
-}
-
-
-/*!
  * \brief Unlink a dialog from the dialogs container, as well as any other places
  * that it may be currently stored.
  *
@@ -3069,11 +3059,18 @@
 	if (pvt->final_destruction_scheduled) {
 		return; /* This is already scheduled for final destruction, let the scheduler take care of it. */
 	}
-	if(pvt->needdestroy != 1) {
+	append_history(pvt, "NeedDestroy", "Setting needdestroy because %s", reason);
+	if (!pvt->needdestroy) {
+		/*
+		 * We unlink this dialog and link again into the
+		 * dialogs_needdestroy container so its not in there twice.
+		 */
+		ao2_lock(dialogs_needdestroy);
+		ao2_t_unlink(dialogs_needdestroy, pvt, "unlink pvt into dialogs_needdestroy container");
+		pvt->needdestroy = 1;
 		ao2_t_link(dialogs_needdestroy, pvt, "link pvt into dialogs_needdestroy container");
-	}
-	append_history(pvt, "NeedDestroy", "Setting needdestroy because %s", reason);
-	pvt->needdestroy = 1;
+		ao2_unlock(dialogs_needdestroy);
+	}
 }
 
 /*! \brief Initialize the initital request packet in the pvt structure.
@@ -4769,6 +4766,9 @@
  * Using empty if-bodies instead of goto's while avoiding unnecessary indents */
 static int realtime_peer_by_name(const char *const *name, struct ast_sockaddr *addr, const char *ipaddr, struct ast_variable **var, struct ast_variable **varregs)
 {
+	if (!ast_check_realtime("sippeers")) {
+		return 0;
+	}
 	/* Peer by name and host=dynamic */
 	if ((*var = ast_load_realtime("sippeers", "name", *name, "host", "dynamic", SENTINEL))) {
 		;
@@ -11474,9 +11474,14 @@
 	/* Update lastrtprx when we send our SDP */
 	p->lastrtprx = p->lastrtptx = time(NULL); /* XXX why both ? */
 
-	/* we unlink this dialog and link again into the dialogs_rtpcheck container to doesnt add it twice */
+	/* 
+	* We unlink this dialog and link again into the 
+	* dialogs_rtpcheck container to doesnt add it twice 
+	*/
+	ao2_lock(dialogs_rtpcheck);
 	ao2_t_unlink(dialogs_rtpcheck, p, "unlink pvt into dialogs_rtpcheck container");
 	ao2_t_link(dialogs_rtpcheck, p, "link pvt into dialogs_rtpcheck container");
+	ao2_unlock(dialogs_rtpcheck);
 
 
 	ast_debug(3, "Done building SDP. Settling with this capability: %s\n", ast_getformatname_multiple(buf, SIPBUFSIZE, capability));
@@ -15639,7 +15644,7 @@
 		return AUTH_DONT_KNOW;
 	}
 
-	if (!ast_apply_ha(peer->ha, addr)) {
+	if (peer->ha && !ast_apply_ha(peer->ha, addr)) {
 		ast_debug(2, "Found peer '%s' for '%s', but fails host access\n", peer->name, of);
 		unref_peer(peer, "unref_peer: check_peer_ok: from find_peer call, early return of AUTH_ACL_FAILED");
 		return AUTH_ACL_FAILED;
@@ -16624,28 +16629,33 @@
 	}
 }
 
-/*! \brief Check RTP Timeout on dialogs
+/*! 
+ * \brief Check RTP Timeout on dialogs
+ *
  * \details This is used with ao2_callback to check rtptimeout
- * rtponholdtimeout and send rtpkeepalive packets
+ * rtponholdtimeout and send rtpkeepalive packets.
+ *
+ * \return CMP_MATCH for items to be unlinked from dialogs_rtpcheck.
  */
 static int dialog_checkrtp_cb(void *dialogobj, void *arg, int flags)
 {
 	struct sip_pvt *dialog = dialogobj;
 	time_t *t = arg;
+	int match_status;
 
 	if (sip_pvt_trylock(dialog)) {
 		return 0;
 	}
 
 	if (dialog->rtp || dialog->vrtp) {
-		check_rtp_timeout(dialog, *t);
+		match_status = check_rtp_timeout(dialog, *t);
 	} else {
-		/* Dialog has no active RTP or VRTP. unlink it from the checkrtp container */
-		dialog_unlink_rtpcheck(dialog);
+		/* Dialog has no active RTP or VRTP. unlink it from the dialogs_rtpcheck container */
+		match_status = CMP_MATCH;
 	}
 	sip_pvt_unlock(dialog);
 
-	return 0;
+	return match_status;
 }
 
 
@@ -25316,36 +25326,43 @@
 	return 0;
 }
 
-/*! \brief helper function for the monitoring thread -- seems to be called with the assumption that the dialog is locked */
-static void check_rtp_timeout(struct sip_pvt *dialog, time_t t)
-{
-
+/*! 
+ * \brief helper function for the monitoring thread -- seems to be called with the assumption that the dialog is locked 
+ * 
+ * \return CMP_MATCH for items to be unlinked from dialogs_rtpcheck.
+ */
+static int check_rtp_timeout(struct sip_pvt *dialog, time_t t)
+{
+
+	if (!dialog->rtp) {
+		/*
+		 * We have no RTP. Since we don't do much with video RTP for 
+		 * now, stop checking this dialog.
+		 */
+		return CMP_MATCH;
+	}
 	/* If we have no active owner, no need to check timers */
 	if (!dialog->owner) {
-		dialog_unlink_rtpcheck(dialog);
-		return;
+		return CMP_MATCH;
 	}
 
 	/* If the call is redirected outside Asterisk, no need to check timers */
 	if (!ast_sockaddr_isnull(&dialog->redirip)) {
-		dialog_unlink_rtpcheck(dialog);
-		return;
+		return CMP_MATCH;
 	}
 
 	/* If the call is involved in a T38 fax session do not check RTP timeout */
 	if (dialog->t38.state == T38_ENABLED) {
-		dialog_unlink_rtpcheck(dialog);
-		return;
+		return CMP_MATCH;
 	}
 	/* If the call is not in UP state return for later check. */
 	if (dialog->owner->_state != AST_STATE_UP) {
-		return;
+		return 0;
 	}
 
 	/* If we have no timers set, return now */
 	if (!ast_rtp_instance_get_keepalive(dialog->rtp) && !ast_rtp_instance_get_timeout(dialog->rtp) && !ast_rtp_instance_get_hold_timeout(dialog->rtp)) {
-		dialog_unlink_rtpcheck(dialog);
-		return;
+		return CMP_MATCH;
 	}
 
 	/* Check AUDIO RTP keepalives */
@@ -25372,7 +25389,7 @@
 					 * Don't block, just try again later.
 					 * If there was no owner, the call is dead already.
 					 */
-					return;
+					return 0;
 				}
 				ast_log(LOG_NOTICE, "Disconnecting call '%s' for lack of RTP activity in %ld seconds\n",
 					dialog->owner->name, (long) (t - dialog->lastrtprx));
@@ -25389,10 +25406,12 @@
 					ast_rtp_instance_set_timeout(dialog->vrtp, 0);
 					ast_rtp_instance_set_hold_timeout(dialog->vrtp, 0);
 				}
-				dialog_unlink_rtpcheck(dialog); /* finally unlink the dialog from the checkrtp container */
-			}
-		}
-	}
+				/* finally unlink the dialog from the checkrtp container */
+				return CMP_MATCH;
+			}
+		}
+	}
+	return 0;
 }
 
 /*! \brief The SIP monitoring thread
@@ -25437,12 +25456,12 @@
 
 		/* Check for dialogs with rtp and rtptimeout
 		 * All Dialogs which have rtp are in dialogs_rtpcheck container*/
-		ao2_t_callback(dialogs_rtpcheck, OBJ_NODATA | OBJ_MULTIPLE, dialog_checkrtp_cb, &t,
+		ao2_t_callback(dialogs_rtpcheck, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, dialog_checkrtp_cb, &t,
 				"callback to check rtptimeout and hangup calls if necessary");
 		/* Check for dialogs marked to be destroyed
 		 * All Dialogs which need Destroy are in dialogs_needdestroy container*/
 		ao2_t_callback(dialogs_needdestroy, OBJ_NODATA | OBJ_MULTIPLE, dialog_needdestroy, &t,
-				"callback to check rtptimeout and hangup calls if necessary");
+				"callback to check dialogs which need to be destroyed");
 
 		/* XXX TODO The scheduler usage in this module does not have sufficient
 		 * synchronization being done between running the scheduler and places




More information about the asterisk-commits mailing list