[svn-commits] murf: branch murf/bug11210 r103675 - /team/murf/bug11210/channels/chan_sip.c

SVN commits to the Digium repositories svn-commits at lists.digium.com
Thu Feb 14 12:22:32 CST 2008


Author: murf
Date: Thu Feb 14 12:22:31 2008
New Revision: 103675

URL: http://svn.digium.com/view/asterisk?view=rev&rev=103675
Log:
Finally, I've figured out why dialog destruction for those recorded in the peer->call field weren't always happening. It was a dependency cycle between the peer destruct func and the dialog destruct func. Copied the code from sip_destroy to unlink_all to unref the peer->call and dialog->relatedpeer if they are set.... I didn't spot this earlier because I was stopping the tests too early. THis happens in the peer_poke code several seconds after asterisk starts and the sip channel driver is activated.

Modified:
    team/murf/bug11210/channels/chan_sip.c

Modified: team/murf/bug11210/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/murf/bug11210/channels/chan_sip.c?view=diff&rev=103675&r1=103674&r2=103675
==============================================================================
--- team/murf/bug11210/channels/chan_sip.c (original)
+++ team/murf/bug11210/channels/chan_sip.c Thu Feb 14 12:22:31 2008
@@ -2417,6 +2417,13 @@
 		dialog_unref(dialog, "removing extension_state, should unref the associated dialog ptr that was stored there.");
 		dialog->stateid = -1; /* shouldn't we 'zero' this out? */
 	}
+	/* Remove link from peer to subscription of MWI */
+	if (dialog->relatedpeer && dialog->relatedpeer->mwipvt)
+		dialog->relatedpeer->mwipvt = dialog_unref(dialog->relatedpeer->mwipvt, "delete ->relatedpeer->mwipvt");
+	if (dialog->relatedpeer && dialog->relatedpeer->call == dialog)
+		dialog->relatedpeer->call = dialog_unref(dialog->relatedpeer->call, "unset the relatedpeer->call field in tandem with relatedpeer field itself");
+	else if (dialog->relatedpeer && dialog->relatedpeer->call != dialog)
+		ast_log(LOG_NOTICE,"dialog relatedpeer field points to peer that doesn't point back (peer->call is %p)\n", dialog->relatedpeer->call);
 
 	/* remove all current packets in this dialog */
 	while((cp = dialog->packets)) {
@@ -4360,6 +4367,12 @@
 	/* Remove link from peer to subscription of MWI */
 	if (p->relatedpeer && p->relatedpeer->mwipvt)
 		p->relatedpeer->mwipvt = dialog_unref(p->relatedpeer->mwipvt, "delete ->relatedpeer->mwipvt");
+	if (p->relatedpeer && p->relatedpeer->call == p)
+		p->relatedpeer->call = dialog_unref(p->relatedpeer->call, "unset the relatedpeer->call field in tandem with relatedpeer field itself");
+	else if (p->relatedpeer && p->relatedpeer->call != p)
+		ast_log(LOG_NOTICE,"The dialog %p's relatedpeer (%p [%s]) does not point back to this dialog, but rather to dialog %p.\n",
+				p, p->relatedpeer, p->relatedpeer->name, p->relatedpeer->call);
+	
 	if (p->relatedpeer)
 		p->relatedpeer = unref_peer(p->relatedpeer,"unsetting a dialog relatedpeer field in sip_destroy");
 	
@@ -5970,23 +5983,6 @@
 			.callid = callid,
 		};			
 		sip_pvt_ptr = ao2_t_find(dialogs, &tmp_dialog, OBJ_POINTER, "ao2_find in dialogs");
-#ifdef DIALOG_DEBUG
-		if (sip_pvt_ptr) {
-			int rc;
-			rc = ao2_t_ref(sip_pvt_ptr, 0, "");
-		}
-		if (!sip_pvt_ptr) {
-			struct ao2_iterator i;
-			struct sip_pvt *d2;
-			
-			i = ao2_iterator_init(dialogs, 0);
-			
-			while ((d2 = ao2_t_iterator_next(&i, "iterate thru dialogs "))) {
-				ast_log(LOG_NOTICE, "Dialogs:  %s\n", d2->callid);
-				ao2_t_ref(d2, -1, "done with d2 pointer");
-			}
-		}
-#endif
 		if (sip_pvt_ptr) {  /* well, if we don't find it-- what IS in there? */
 			/* Found the call */
 			sip_pvt_lock(sip_pvt_ptr);
@@ -7554,7 +7550,7 @@
 	struct sip_pvt *p = NULL;
 
 	if (!(p = ast_threadstorage_get(&ts_temp_pvt, sizeof(*p)))) {
-		ast_log(LOG_NOTICE, "Failed to get temporary pvt\n");
+		ast_log(LOG_ERROR, "Failed to get temporary pvt\n");
 		return -1;
 	}
 
@@ -9243,7 +9239,6 @@
 			ast_log(LOG_WARNING, "Unable to allocate registration transaction (memory or socket error)\n");
 			return 0;
 		}
-		ast_log(LOG_NOTICE,"Allocated SIP pvt dialog %p in transmit_register!\n", p);
 		
 		if (p->do_history)
 			append_history(p, "RegistryInit", "Account: %s@%s", r->username, r->hostname);
@@ -9630,7 +9625,7 @@
 	    ast_test_flag(&peer->flags[1], SIP_PAGE2_RTAUTOCLEAR)) {
 		ao2_t_unlink(peers, peer, "ao2_unlink of peer from peers table");
 		if (peer->addr.sin_addr.s_addr) {
-			ao2_t_unlink(peers_by_ip, peer, "ao2_unlink of peer from peers table");
+			ao2_t_unlink(peers_by_ip, peer, "ao2_unlink of peer from peers_by_ip table");
 		}
 		
 	}
@@ -10434,7 +10429,7 @@
 		if (peer) {
 			ao2_t_link(peers, peer, "link peer into peer table");
 			if (peer->addr.sin_addr.s_addr) {
-				ao2_t_link(peers_by_ip, peer, "link peer into peer table");
+				ao2_t_link(peers_by_ip, peer, "link peer into peers-by-ip table");
 			}
 			
 			if (sip_cancel_destroy(p))
@@ -17913,7 +17908,6 @@
 		}
 		if (authpeer->mwipvt && authpeer->mwipvt != p) {	/* Destroy old PVT if this is a new one */
 			/* We only allow one subscription per peer */
-			ast_log(LOG_NOTICE, "Calling Sip_Destroy() from subscribe request for %s....\n", authpeer->mwipvt->callid);
 			dialog_unlink_all(authpeer->mwipvt, TRUE, TRUE);
 			authpeer->mwipvt = dialog_unref(authpeer->mwipvt, "unref dialog authpeer->mwipvt");
 			/* sip_destroy(authpeer->mwipvt); */
@@ -18750,11 +18744,9 @@
 	}
 	if (monitor_thread != AST_PTHREADT_NULL) {
 		/* Wake up the thread */
-		ast_log(LOG_NOTICE, "about to sigurg the SIP monitor thread.");
 		pthread_kill(monitor_thread, SIGURG);
 	} else {
 		/* Start a new monitor */
-		ast_log(LOG_NOTICE, "about to fire up a thread for the SIP do_monitor().");
 		if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
 			ast_mutex_unlock(&monlock);
 			ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
@@ -19128,7 +19120,8 @@
 {
 	struct sip_pvt *p;
 	int xmitres = 0;
-
+	char mbuf3[200];
+	
 	if (!peer->maxms || !peer->addr.sin_addr.s_addr) {
 		/* IF we have no IP, or this isn't to be monitored, return
 		  immediately after clearing things out */
@@ -19148,7 +19141,8 @@
 	}
 	if (!(p = sip_alloc(NULL, NULL, 0, SIP_OPTIONS)))
 		return -1;
-	peer->call = dialog_ref(p, "copy sip alloc from p to peer->call");
+	sprintf(mbuf3,"copy sip alloc from p to peer->call (peer is %p [%s])", peer, peer->name);
+	peer->call = dialog_ref(p, mbuf3);
 	
 	p->sa = peer->addr;
 	p->recv = peer->addr;
@@ -20925,58 +20919,39 @@
 	if (reason != CHANNEL_MODULE_LOAD) {
 		ast_debug(4, "--------------- SIP reload started\n");
 
-		ast_log(LOG_NOTICE, "Reload: #1a -- about to clear realm authentication\n");
 		clear_realm_authentication(authl);
-		ast_log(LOG_NOTICE, "Reload: #1b -- about to clear sip domains\n");
 		clear_sip_domains();
-		ast_log(LOG_NOTICE, "Reload: #1c -- about to traverse and destroy registry related dialogs\n");
 		authl = NULL;
 
 		/* First, destroy all outstanding registry calls */
 		/* This is needed, since otherwise active registry entries will not be destroyed */
 		ASTOBJ_CONTAINER_TRAVERSE(&regl, 1, do {  /* regl is locked */
-				ast_log(LOG_NOTICE, "#1c.1. About to get iterator lock for registry entry ");
 				
 				/* avoid a deadlock in the unlink_all call, if iterator->call's (a dialog) registry entry
 				   is this registry entry. In other words, if the dialog we are pointing to points back to 
 				   us, then if we get a lock on this object, and try to UNREF it, we will deadlock, because
 				   we already ... NO. This is not the problem. */
-#ifdef INANE_ATTEMPT_AT_HUMOR
-				if (iterator->call && iterator->call->registry && iterator->call->registry->call == iterator->call)
-					iterator->call->registry->call = dialog_unref(iterator->call, "null out the registry's call dialog field before unlink_all");
-				if (iterator->call && iterator->call->registry)
-					iterator->call->registry = registry_unref(iterator->call->registry, "delete dialog's registry entry before unlink_all");
-				ast_log(LOG_NOTICE, "#1c.2. Right now....");
-#endif
 				ASTOBJ_RDLOCK(iterator); /* was RDLOCK  and now regl is locked, and the object is also locked */
 				if (iterator->call) {
 					ast_debug(3, "Destroying active SIP dialog for registry %s@%s\n", iterator->username, iterator->hostname);
-					ast_log(LOG_NOTICE, "#1c.3. There's a dialog...unlinking it...");
 					/* This will also remove references to the registry */
 					dialog_unlink_all(iterator->call, TRUE, TRUE);
-					ast_log(LOG_NOTICE, "#1c.4. Unreffing that dialog...");
 					iterator->call = dialog_unref(iterator->call, "remove iterator->call from registry traversal");
 					/* iterator->call = sip_destroy(iterator->call); */
 				}
-				ast_log(LOG_NOTICE, "#1c.5. About to release iterator's registry lock...");
 				ASTOBJ_UNLOCK(iterator);
 				
 		} while(0));
 
-		ast_log(LOG_NOTICE, "Reload: #1d -- about to destroy all the users\n");
 		/* Then, actually destroy users and registry */
 		ao2_t_ref(users, -1, "destroy users table");
 		ast_debug(4, "--------------- Done destroying user list\n");
-		ast_log(LOG_NOTICE, "Reload: #1e -- about to destroy all the registry entries\n");
 		ASTOBJ_CONTAINER_DESTROYALL(&regl, sip_registry_destroy);
 		ast_debug(4, "--------------- Done destroying registry list\n");
-		ast_log(LOG_NOTICE, "Reload: #1f -- about to mark all the peer entries for destruction\n");
 		ao2_t_callback(peers, OBJ_NODATA, peer_markall_func, 0, "callback to mark all peers");
 		/* reinstate the user table */
-		ast_log(LOG_NOTICE, "Reload: #1g -- about to reallocate the user table\n");
 		users = ao2_t_container_alloc(hash_user_size, user_hash_cb, user_cmp_cb, "allocate users");
 	}
-	ast_log(LOG_NOTICE, "Reload: #2\n");
 	
 	/* Reset certificate handling for TLS sessions */
 	default_tls_cfg.certfile = ast_strdup(AST_CERTFILE); /*XXX Not sure if this is useful */
@@ -21100,7 +21075,6 @@
 	ast_clear_flag(&global_flags[1], SIP_PAGE2_VIDEOSUPPORT);
 	ast_clear_flag(&global_flags[1], SIP_PAGE2_TEXTSUPPORT);
 
-	ast_log(LOG_NOTICE, "Reload: #3\n");
 
 	/* Read the [general] config section of sip.conf (or from realtime config) */
 	for (v = ast_variable_browse(cfg, "general"); v; v = v->next) {
@@ -21465,7 +21439,6 @@
 		ast_log(LOG_WARNING, "To disallow external domains, you need to configure local SIP domains.\n");
 		allow_external_domains = 1;
 	}
-	ast_log(LOG_NOTICE, "Reload: #4\n");
 	
 	/* Build list of authentication to various SIP realms, i.e. service providers */
  	for (v = ast_variable_browse(cfg, "authentication"); v ; v = v->next) {
@@ -21529,7 +21502,6 @@
 		ast_config_destroy(ucfg);
 	}
 	
-	ast_log(LOG_NOTICE, "Reload: #5\n");
 
 	/* Load peers, users and friends */
 	cat = NULL;
@@ -21625,7 +21597,6 @@
 			ast_inet_ntoa(externip.sin_addr) , ntohs(externip.sin_port));
 	}
 	ast_mutex_unlock(&netlock);
-	ast_log(LOG_NOTICE, "Reload: #7\n");
 
 	/* Add default domains - host name, IP address and IP:port */
 	/* Only do this if user added any sip domain with "localdomains" */
@@ -21653,7 +21624,6 @@
 			add_sip_domain(temp, SIP_DOMAIN_AUTO, NULL);
 	}
 
-	ast_log(LOG_NOTICE, "Reload: #8\n");
 	/* Release configuration from memory */
 	ast_config_destroy(cfg);
 
@@ -22376,7 +22346,6 @@
 	ast_manager_unregister("SIPpeers");
 	ast_manager_unregister("SIPshowpeer");
 	ast_manager_unregister("SIPshowregistry");
-	ast_log(LOG_NOTICE, "About to hangup dialogs\n");
 	
 	/* Kill TCP/TLS server threads */
 	if (sip_tcp_desc.master)
@@ -22404,7 +22373,6 @@
 			ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
 		ao2_t_ref(p, -1, "toss dialog ptr from iterator_next");
 	}
-	ast_log(LOG_NOTICE, "...Done! Now, grab a monitor lock and join threads...\n");
 
 	ast_mutex_lock(&monlock);
 	if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
@@ -22414,7 +22382,6 @@
 	}
 	monitor_thread = AST_PTHREADT_STOP;
 	ast_mutex_unlock(&monlock);
-	ast_log(LOG_NOTICE, "...Done! Now, grab the dialoglist lock and get rid of the dialogs...\n");
 
 	/* Destroy all the dialogs and free their memory */
 	i = ao2_iterator_init(dialogs, 0);
@@ -22423,14 +22390,11 @@
 		ao2_t_ref(p, -1, "throw away iterator result"); 
 	}
 
-	ast_log(LOG_NOTICE, "...Done! Now, free up the ha's...\n");
 	/* Free memory for local network address mask */
 	ast_free_ha(localaddr);
 
-	ast_log(LOG_NOTICE, "...Done! Now, free up the realm_authentication...\n");
 	clear_realm_authentication(authl);
 
-	ast_log(LOG_NOTICE, "...Done! Now, free up the registry entries...\n");
 
 	if (default_tls_cfg.certfile)
 		ast_free(default_tls_cfg.certfile);
@@ -22442,29 +22406,19 @@
 		ast_free(default_tls_cfg.capath);
 
 	ASTOBJ_CONTAINER_DESTROYALL(&regl, sip_registry_destroy);
-	ast_log(LOG_NOTICE, "...Done! Now, free up the registry List...\n");
 	ASTOBJ_CONTAINER_DESTROY(&regl);
-	ast_log(LOG_NOTICE, "...Done! Now, free up the peers...\n");
 
 	ao2_t_ref(peers, -1, "unref the peers table");
-	ast_log(LOG_NOTICE, "...Done! Now, free up the peers-by-ip...\n");
 	ao2_t_ref(peers_by_ip, -1, "unref the peers_by_ip table");
-	ast_log(LOG_NOTICE, "...Done! Now, free up the users...\n");
 	ao2_t_ref(users, -1, "unref the users table");
-	ast_log(LOG_NOTICE, "...Done! Now, free up the dialogs table itself...\n");
 	ao2_t_ref(dialogs, -1, "unref the dialogs table");
-	ast_log(LOG_NOTICE, "...Done! Now, clear up the sip domains info...\n");
 
 	clear_sip_domains();
-	ast_log(LOG_NOTICE, "...Done! Now, close the sip socket...\n");
 	close(sipsock);
-	ast_log(LOG_NOTICE, "...Done! Now, destroy the scheduler's context...\n");
 	sched_context_destroy(sched);
-	ast_log(LOG_NOTICE, "...Done! Now, destroy the scheduler's used context...\n");
 	con = ast_context_find(used_context);
 	if (con)
 		ast_context_destroy(con, "SIP");
-	ast_log(LOG_NOTICE, "...Done!\n");
 
 	return 0;
 }




More information about the svn-commits mailing list