From e5a15cde311425d73b280bdc1b6f811c1591a33d Mon Sep 17 00:00:00 2001
From: Anthony Minessale <anthm@freeswitch.org>
Date: Wed, 15 Aug 2012 15:11:57 -0500
Subject: [PATCH] debug lost read lock

---
 src/include/switch_core.h           | 23 +++++++++--------------
 src/mod/endpoints/mod_sofia/sofia.c | 13 ++++++++-----
 src/switch_core_session.c           | 14 ++++----------
 3 files changed, 21 insertions(+), 29 deletions(-)

diff --git a/src/include/switch_core.h b/src/include/switch_core.h
index 879951cfde..dcaace2724 100644
--- a/src/include/switch_core.h
+++ b/src/include/switch_core.h
@@ -742,13 +742,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_set_codec_slin(switch_core_s
 */
 SWITCH_DECLARE(char *) switch_core_get_uuid(void);
 
-#ifdef SWITCH_DEBUG_RWLOCKS
-SWITCH_DECLARE(switch_core_session_t *) switch_core_session_perform_locate(const char *uuid_str, const char *file, const char *func, int line);
-#endif
 
-#ifdef SWITCH_DEBUG_RWLOCKS
+SWITCH_DECLARE(switch_core_session_t *) switch_core_session_perform_locate(const char *uuid_str, const char *file, const char *func, int line);
 SWITCH_DECLARE(switch_core_session_t *) switch_core_session_perform_force_locate(const char *uuid_str, const char *file, const char *func, int line);
-#endif
+
 
 /*! 
   \brief Locate a session based on it's uuid
@@ -756,11 +753,8 @@ SWITCH_DECLARE(switch_core_session_t *) switch_core_session_perform_force_locate
   \return the session or NULL
   \note if the session was located it will have a read lock obtained which will need to be released with switch_core_session_rwunlock()
 */
-#ifdef SWITCH_DEBUG_RWLOCKS
+
 #define switch_core_session_locate(uuid_str) switch_core_session_perform_locate(uuid_str, __FILE__, __SWITCH_FUNC__, __LINE__)
-#else
-SWITCH_DECLARE(switch_core_session_t *) switch_core_session_locate(_In_z_ const char *uuid_str);
-#endif
 
 /*! 
   \brief Locate a session based on it's uuid even if the channel is not ready
@@ -768,11 +762,9 @@ SWITCH_DECLARE(switch_core_session_t *) switch_core_session_locate(_In_z_ const
   \return the session or NULL
   \note if the session was located it will have a read lock obtained which will need to be released with switch_core_session_rwunlock()
 */
-#ifdef SWITCH_DEBUG_RWLOCKS
+
 #define switch_core_session_force_locate(uuid_str) switch_core_session_perform_force_locate(uuid_str, __FILE__, __SWITCH_FUNC__, __LINE__)
-#else
-SWITCH_DECLARE(switch_core_session_t *) switch_core_session_force_locate(_In_z_ const char *uuid_str);
-#endif
+
 
 /*! 
   \brief Retrieve a global variable from the core
@@ -831,7 +823,10 @@ SWITCH_DECLARE(void) switch_core_session_hupall_endpoint(const switch_endpoint_i
   \param partner [out] The session's partner, or NULL if it wasnt found
   \return SWITCH_STATUS_SUCCESS or SWITCH_STATUS_FALSE if this session isn't bridged
 */
-SWITCH_DECLARE(switch_status_t) switch_core_session_get_partner(switch_core_session_t *session, switch_core_session_t **partner);
+SWITCH_DECLARE(switch_status_t) switch_core_session_perform_get_partner(switch_core_session_t *session, switch_core_session_t **partner,
+																		const char *file, const char *func, int line);
+
+#define switch_core_session_get_partner(_session, _partner) switch_core_session_perform_get_partner(_session, _partner, __FILE__, __SWITCH_FUNC__, __LINE__)
 
 /*! 
   \brief Send a message to another session using it's uuid
diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c
index f21d92b5c4..58a658e9ea 100644
--- a/src/mod/endpoints/mod_sofia/sofia.c
+++ b/src/mod/endpoints/mod_sofia/sofia.c
@@ -6240,16 +6240,18 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
 		if (!sofia_test_flag(tech_pvt, TFLAG_SDP)) {
 			if (switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
 				private_object_t *other_tech_pvt = switch_core_session_get_private(other_session);
+				int r = sofia_test_flag(other_tech_pvt, TFLAG_REINVITED);
+				switch_core_session_rwunlock(other_session);
 
-				if(sofia_test_flag(other_tech_pvt, TFLAG_REINVITED)) {
-
+				if (r) {
 					/* Due to a race between simultaneous reinvites to both legs of a bridge,
 					  an earlier call to nua_invite silently failed.
 					  So we reject the incoming invite with a 491 and redo the failed outgoing invite. */
 
-					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Other leg already handling a reinvite, so responding with 491\n");
+					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, 
+									  "Other leg already handling a reinvite, so responding with 491\n");
+
 					nua_respond(tech_pvt->nh, SIP_491_REQUEST_PENDING, TAG_END());
-					switch_core_session_rwunlock(other_session);
 					sofia_glue_do_invite(session);
 					goto done;
 				}
@@ -6498,6 +6500,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
 								switch_yield(250000);
 								launch_media_on_hold(session);
 
+								switch_core_session_rwunlock(other_session);
 								goto done;
 							}
 						}
@@ -6516,7 +6519,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
 							/* The other leg won the reinvite race */
 							switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Other leg already handling reinvite, so responding with 491\n");
 							nua_respond(tech_pvt->nh, SIP_491_REQUEST_PENDING, TAG_END());
-						        switch_core_session_rwunlock(other_session);
+							switch_core_session_rwunlock(other_session);
 							goto done;
 						}
 						sofia_set_flag(tech_pvt, TFLAG_REINVITED);
diff --git a/src/switch_core_session.c b/src/switch_core_session.c
index 66c39f7056..e3262899a6 100644
--- a/src/switch_core_session.c
+++ b/src/switch_core_session.c
@@ -105,11 +105,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_set_codec_slin(switch_core_s
 }
 
 
-#ifdef SWITCH_DEBUG_RWLOCKS
 SWITCH_DECLARE(switch_core_session_t *) switch_core_session_perform_locate(const char *uuid_str, const char *file, const char *func, int line)
-#else
-SWITCH_DECLARE(switch_core_session_t *) switch_core_session_locate(const char *uuid_str)
-#endif
 {
 	switch_core_session_t *session = NULL;
 
@@ -139,11 +135,8 @@ SWITCH_DECLARE(switch_core_session_t *) switch_core_session_locate(const char *u
 
 
 
-#ifdef SWITCH_DEBUG_RWLOCKS
+
 SWITCH_DECLARE(switch_core_session_t *) switch_core_session_perform_force_locate(const char *uuid_str, const char *file, const char *func, int line)
-#else
-SWITCH_DECLARE(switch_core_session_t *) switch_core_session_force_locate(const char *uuid_str)
-#endif
 {
 	switch_core_session_t *session = NULL;
 	switch_status_t status;
@@ -180,12 +173,13 @@ SWITCH_DECLARE(switch_core_session_t *) switch_core_session_force_locate(const c
 }
 
 
-SWITCH_DECLARE(switch_status_t) switch_core_session_get_partner(switch_core_session_t *session, switch_core_session_t **partner)
+SWITCH_DECLARE(switch_status_t) switch_core_session_perform_get_partner(switch_core_session_t *session, switch_core_session_t **partner,
+																		const char *file, const char *func, int line)
 {
 	const char *uuid;
 
 	if ((uuid = switch_channel_get_partner_uuid(session->channel))) {
-		if ((*partner = switch_core_session_locate(uuid))) {
+		if ((*partner = switch_core_session_perform_locate(uuid, file, func, line))) {
 			return SWITCH_STATUS_SUCCESS;
 		}
 	}