]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
MODSOFIA-57 fix edge case if a session is blocked during a sip profile shutdown
authorMathieu Rene <mrene@avgs.ca>
Tue, 16 Feb 2010 00:07:50 +0000 (00:07 +0000)
committerMathieu Rene <mrene@avgs.ca>
Tue, 16 Feb 2010 00:07:50 +0000 (00:07 +0000)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@16654 d0543943-73ff-0310-b7d9-9358b9ac24b2

src/mod/endpoints/mod_sofia/mod_sofia.c
src/mod/endpoints/mod_sofia/mod_sofia.h
src/mod/endpoints/mod_sofia/sofia.c
src/mod/endpoints/mod_sofia/sofia_glue.c
src/mod/endpoints/mod_sofia/sofia_reg.c

index 93e1a7be6ce2ec805ae40b803ebabb2a8d69d6fe..f076bdf2cf6d5bb30ebd9aa404f5b032b8a87071 100644 (file)
@@ -362,6 +362,10 @@ switch_status_t sofia_on_destroy(switch_core_session_t *session)
                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_status_t sofia_on_hangup(switch_core_session_t *session)
        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);
 
index 55c970ced934a1fd814918412d2103837db4621c..7bb7c2d3259a091b2c26bdba97d882a466eb7b14 100644 (file)
@@ -206,6 +206,7 @@ typedef enum {
        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 @@ void sofia_glue_release_profile__(const char *file, const char *func, int line,
 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_t *sofia_reg_find_gateway_by_realm__(const char *file, const char
 
 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 @@ int sofia_sla_supported(sip_t const *sip);
 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);
index 901c0afe6a75f254d1d0a32e092c7846c9fd3c94..38846c0c480943588033a6cab8d9f104a239f518 100644 (file)
@@ -682,6 +682,8 @@ void sofia_event_callback(nua_event_t event,
        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 @@ void sofia_event_callback(nua_event_t event,
                        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 @@ void sofia_event_callback(nua_event_t event,
                        }
                }
        }
-
+       
+       
        if (sofia_test_pflag(profile, PFLAG_AUTH_ALL) && tech_pvt && tech_pvt->key && sip) {
                sip_authorization_t const *authorization = NULL;
 
@@ -1527,8 +1531,8 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t *thread, void
        if (sofia_test_pflag(profile, PFLAG_RESPAWN)) {
                config_sofia(1, profile->name);
        }
-
-       switch_core_destroy_memory_pool(&pool);
+       
+       sofia_profile_destroy(profile);
 
   end:
        switch_mutex_lock(mod_sofia_globals.mutex);
@@ -1538,6 +1542,16 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t *thread, void
        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;
index ea3725ead060fd295a49c70d735e7763a5c623a0..987e25cbf684a8d330d305331346c77ac7d9cd0e 100644 (file)
@@ -3776,6 +3776,19 @@ char *sofia_glue_get_url_from_contact(char *buf, uint8_t to_dup)
        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 @@ sofia_profile_t *sofia_glue_find_profile__(const char *file, const char *func, i
                        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 @@ sofia_profile_t *sofia_glue_find_profile__(const char *file, const char *func, i
                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;
index 0ff4fcf9c99ff79929e86844a0c7db4722afd537..5248ad840b42f339f0c6cfa861a9cc48f0f23671 100644 (file)
@@ -320,8 +320,9 @@ void sofia_reg_check_gateway(sofia_profile_t *profile, time_t now)
                        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 @@ sofia_gateway_t *sofia_reg_find_gateway__(const char *file, const char *func, in
                        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,6 +2392,19 @@ sofia_gateway_t *sofia_reg_find_gateway_by_realm__(const char *file, const char
        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)
 {