Revision
16654
Author
mrene
Date
2010-02-15 18:07:50 -0600 (Mon, 15 Feb 2010)

Log Message

MODSOFIA-57 fix edge case if a session is blocked during a sip profile shutdown

Modified Paths

Diff

Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c (16653 => 16654)


--- freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c	2010-02-15 23:59:36 UTC (rev 16653)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c	2010-02-16 00:07:50 UTC (rev 16654)
@@ -362,6 +362,10 @@
 		switch_mutex_unlock(tech_pvt->profile->flag_mutex);
 
 		sofia_glue_deactivate_rtp(tech_pvt);
+		
+		if (sofia_test_pflag(tech_pvt->profile, PFLAG_DESTROY) && !tech_pvt->profile->inuse) {
+			sofia_profile_destroy(tech_pvt->profile);
+		}
 	}
 
 	return SWITCH_STATUS_SUCCESS;
@@ -376,6 +380,10 @@
 	switch_call_cause_t cause = switch_channel_get_cause(channel);
 	int sip_cause = hangup_cause_to_sip(cause);
 	const char *ps_cause = NULL, *use_my_cause;
+	
+	if (sofia_test_pflag(tech_pvt->profile, PFLAG_DESTROY)) {
+		return SWITCH_STATUS_SUCCESS;
+	}
 
 	switch_mutex_lock(tech_pvt->sofia_mutex);
 

Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.h (16653 => 16654)


--- freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.h	2010-02-15 23:59:36 UTC (rev 16653)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.h	2010-02-16 00:07:50 UTC (rev 16654)
@@ -206,6 +206,7 @@
 	PFLAG_PASS_CALLEE_ID,
 	PFLAG_LOG_AUTH_FAIL,
 	PFLAG_TRACK_CALLS,
+	PFLAG_DESTROY,
 	/* No new flags below this line */
 	PFLAG_MAX
 } PFLAGS;
@@ -837,6 +838,9 @@
 sofia_profile_t *sofia_glue_find_profile__(const char *file, const char *func, int line, const char *key);
 #define sofia_glue_find_profile(x) sofia_glue_find_profile__(__FILE__, __SWITCH_FUNC__, __LINE__,  x)
 
+#define sofia_glue_profile_rdlock(x) sofia_glue_profile_rdlock__(__FILE__, __SWITCH_FUNC__, __LINE__, x)
+switch_status_t sofia_glue_profile_rdlock__(const char *file, const char *func, int line, sofia_profile_t *profile);
+
 switch_status_t sofia_reg_add_gateway(char *key, sofia_gateway_t *gateway);
 sofia_gateway_t *sofia_reg_find_gateway__(const char *file, const char *func, int line, const char *key);
 #define sofia_reg_find_gateway(x) sofia_reg_find_gateway__(__FILE__, __SWITCH_FUNC__, __LINE__,  x)
@@ -846,6 +850,9 @@
 
 sofia_gateway_subscription_t *sofia_find_gateway_subscription(sofia_gateway_t *gateway_ptr, const char *event);
 
+#define sofia_reg_gateway_rdlock(x) sofia_reg_gateway_rdlock__(__FILE__, __SWITCH_FUNC__, __LINE__,  x)
+switch_status_t sofia_reg_gateway_rdlock__(const char *file, const char *func, int line, sofia_gateway_t *gateway);
+
 void sofia_reg_release_gateway__(const char *file, const char *func, int line, sofia_gateway_t *gateway);
 #define sofia_reg_release_gateway(x) sofia_reg_release_gateway__(__FILE__, __SWITCH_FUNC__, __LINE__, x);
 
@@ -964,3 +971,4 @@
 void sofia_glue_tech_untrack(sofia_profile_t *profile, switch_core_session_t *session, switch_bool_t force);
 void sofia_glue_tech_track(sofia_profile_t *profile, switch_core_session_t *session);
 int sofia_glue_recover(switch_bool_t flush);
+void sofia_profile_destroy(sofia_profile_t *profile);

Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c (16653 => 16654)


--- freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c	2010-02-15 23:59:36 UTC (rev 16653)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c	2010-02-16 00:07:50 UTC (rev 16654)
@@ -682,6 +682,8 @@
 	int locked = 0;
 	int check_destroy = 1;
 
+	/* sofia_private will be == &mod_sofia_globals.keep_private whenever a request is done with a new handle that has to be 
+	  freed whenever the request is done */
 	if (nh && sofia_private == &mod_sofia_globals.keep_private) {
 		if (status >= 300) {
 			nua_handle_bind(nh, NULL);
@@ -689,11 +691,12 @@
 			return;
 		}
 	}
+	
 
 	if (sofia_private && sofia_private != &mod_sofia_globals.destroy_private && sofia_private != &mod_sofia_globals.keep_private) {
 		if ((gateway = sofia_private->gateway)) {
-			if (switch_thread_rwlock_tryrdlock(gateway->profile->rwlock) != SWITCH_STATUS_SUCCESS) {
-				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Profile %s is locked\n", gateway->profile->name);
+			/* Released in sofia_reg_release_gateway() */
+			if (sofia_reg_gateway_rdlock(gateway) != SWITCH_STATUS_SUCCESS) {
 				return;
 			}
 		} else if (!zstr(sofia_private->uuid)) {
@@ -733,7 +736,8 @@
 			}
 		}
 	}
-
+	
+	
 	if (sofia_test_pflag(profile, PFLAG_AUTH_ALL) && tech_pvt && tech_pvt->key && sip) {
 		sip_authorization_t const *authorization = NULL;
 
@@ -1527,9 +1531,9 @@
 	if (sofia_test_pflag(profile, PFLAG_RESPAWN)) {
 		config_sofia(1, profile->name);
 	}
+	
+	sofia_profile_destroy(profile);
 
-	switch_core_destroy_memory_pool(&pool);
-
   end:
 	switch_mutex_lock(mod_sofia_globals.mutex);
 	mod_sofia_globals.threads--;
@@ -1538,6 +1542,16 @@
 	return NULL;
 }
 
+void sofia_profile_destroy(sofia_profile_t *profile) 
+{
+	if (!profile->inuse) {
+		switch_memory_pool_t *pool = profile->pool;
+		switch_core_destroy_memory_pool(&pool);
+	} else {
+		sofia_set_pflag(profile, PFLAG_DESTROY);
+	}
+}
+
 void launch_sofia_profile_thread(sofia_profile_t *profile)
 {
 	switch_thread_t *thread;

Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c (16653 => 16654)


--- freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c	2010-02-15 23:59:36 UTC (rev 16653)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c	2010-02-16 00:07:50 UTC (rev 16654)
@@ -3776,6 +3776,19 @@
 	return url;
 }
 
+switch_status_t sofia_glue_profile_rdlock__(const char *file, const char *func, int line, sofia_profile_t *profile)
+{
+	switch_status_t status = switch_thread_rwlock_tryrdlock(profile->rwlock);
+	if (status != SWITCH_STATUS_SUCCESS) {
+		switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_ERROR, "Profile %s is locked\n", profile->name);
+		return status;
+	}
+#ifdef SOFIA_DEBUG_RWLOCKS
+	switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_ERROR, "XXXXXXXXXXXXXX LOCK %s\n", profile->name);
+#endif
+	return status;
+}
+
 sofia_profile_t *sofia_glue_find_profile__(const char *file, const char *func, int line, const char *key)
 {
 	sofia_profile_t *profile;
@@ -3789,10 +3802,7 @@
 			profile = NULL;
 			goto done;
 		}
-		if (switch_thread_rwlock_tryrdlock(profile->rwlock) != SWITCH_STATUS_SUCCESS) {
-#ifdef SOFIA_DEBUG_RWLOCKS
-			switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_ERROR, "Profile %s is locked\n", profile->name);
-#endif
+		if (sofia_glue_profile_rdlock__(file, func, line, profile) != SWITCH_STATUS_SUCCESS) {
 			profile = NULL;
 		}
 	} else {
@@ -3800,13 +3810,8 @@
 		switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_ERROR, "Profile %s is not in the hash\n", key);
 #endif
 	}
-#ifdef SOFIA_DEBUG_RWLOCKS
-	if (profile) {
-		switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_ERROR, "XXXXXXXXXXXXXX LOCK %s\n", profile->name);
-	}
-#endif
 
-  done:
+done:
 	switch_mutex_unlock(mod_sofia_globals.hash_mutex);
 
 	return profile;

Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_reg.c (16653 => 16654)


--- freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_reg.c	2010-02-15 23:59:36 UTC (rev 16653)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_reg.c	2010-02-16 00:07:50 UTC (rev 16654)
@@ -320,8 +320,9 @@
 			gateway_ptr->status = SOFIA_GATEWAY_DOWN;
 			gateway_ptr->retry = 0;
 
-			if (!gateway_ptr->nh)
+			if (!gateway_ptr->nh) {
 				sofia_reg_new_handle(gateway_ptr, now ? 1 : 0);
+			}
 
 			if (sofia_glue_check_nat(gateway_ptr->profile, gateway_ptr->register_proxy)) {
 				user_via = sofia_glue_create_external_via(NULL, gateway_ptr->profile, gateway_ptr->register_transport);
@@ -2340,16 +2341,10 @@
 			gateway = NULL;
 			goto done;
 		}
-		if (switch_thread_rwlock_tryrdlock(gateway->profile->rwlock) != SWITCH_STATUS_SUCCESS) {
-			switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_ERROR, "Profile %s is locked\n", gateway->profile->name);
+		if (sofia_reg_gateway_rdlock__(file, func, line, gateway) != SWITCH_STATUS_SUCCESS) {
 			gateway = NULL;
 		}
 	}
-	if (gateway) {
-#ifdef SOFIA_DEBUG_RWLOCKS
-		switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, SWITCH_LOG_ERROR, "XXXXXXXXXXXXXX GW LOCK %s\n", gateway->profile->name);
-#endif
-	}
 
   done:
 	switch_mutex_unlock(mod_sofia_globals.hash_mutex);
@@ -2397,7 +2392,20 @@
 	return gateway;
 }
 
+switch_status_t sofia_reg_gateway_rdlock__(const char *file, const char *func, int line, sofia_gateway_t *gateway)
+{
+	switch_status_t status = sofia_glue_profile_rdlock__(file, func, line, gateway->profile);
 
+#ifdef SOFIA_DEBUG_RWLOCKS
+	if (status != SWITCH_STATUS_SUCCESS) {
+		switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, SWITCH_LOG_ERROR, "XXXXXXXXXXXXXX GW LOCK %s\n", gateway->profile->name);		
+	}
+#endif
+
+	return status;
+}
+
+
 void sofia_reg_release_gateway__(const char *file, const char *func, int line, sofia_gateway_t *gateway)
 {
 	switch_thread_rwlock_unlock(gateway->profile->rwlock);