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

git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@16654 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
Mathieu Rene 2010-02-16 00:07:50 +00:00
parent 5dc4d68862
commit 4bcb352602
5 changed files with 66 additions and 23 deletions

View File

@ -362,6 +362,10 @@ switch_status_t sofia_on_destroy(switch_core_session_t *session)
switch_mutex_unlock(tech_pvt->profile->flag_mutex); switch_mutex_unlock(tech_pvt->profile->flag_mutex);
sofia_glue_deactivate_rtp(tech_pvt); 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; return SWITCH_STATUS_SUCCESS;
@ -377,6 +381,10 @@ switch_status_t sofia_on_hangup(switch_core_session_t *session)
int sip_cause = hangup_cause_to_sip(cause); int sip_cause = hangup_cause_to_sip(cause);
const char *ps_cause = NULL, *use_my_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); switch_mutex_lock(tech_pvt->sofia_mutex);
sofia_clear_flag(tech_pvt, TFLAG_RECOVERING); sofia_clear_flag(tech_pvt, TFLAG_RECOVERING);

View File

@ -206,6 +206,7 @@ typedef enum {
PFLAG_PASS_CALLEE_ID, PFLAG_PASS_CALLEE_ID,
PFLAG_LOG_AUTH_FAIL, PFLAG_LOG_AUTH_FAIL,
PFLAG_TRACK_CALLS, PFLAG_TRACK_CALLS,
PFLAG_DESTROY,
/* No new flags below this line */ /* No new flags below this line */
PFLAG_MAX PFLAG_MAX
} PFLAGS; } 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); 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_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); 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); 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) #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); 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); 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); #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_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); void sofia_glue_tech_track(sofia_profile_t *profile, switch_core_session_t *session);
int sofia_glue_recover(switch_bool_t flush); int sofia_glue_recover(switch_bool_t flush);
void sofia_profile_destroy(sofia_profile_t *profile);

View File

@ -682,6 +682,8 @@ void sofia_event_callback(nua_event_t event,
int locked = 0; int locked = 0;
int check_destroy = 1; 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 (nh && sofia_private == &mod_sofia_globals.keep_private) {
if (status >= 300) { if (status >= 300) {
nua_handle_bind(nh, NULL); nua_handle_bind(nh, NULL);
@ -690,10 +692,11 @@ void sofia_event_callback(nua_event_t event,
} }
} }
if (sofia_private && sofia_private != &mod_sofia_globals.destroy_private && sofia_private != &mod_sofia_globals.keep_private) { if (sofia_private && sofia_private != &mod_sofia_globals.destroy_private && sofia_private != &mod_sofia_globals.keep_private) {
if ((gateway = sofia_private->gateway)) { if ((gateway = sofia_private->gateway)) {
if (switch_thread_rwlock_tryrdlock(gateway->profile->rwlock) != SWITCH_STATUS_SUCCESS) { /* Released in sofia_reg_release_gateway() */
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Profile %s is locked\n", gateway->profile->name); if (sofia_reg_gateway_rdlock(gateway) != SWITCH_STATUS_SUCCESS) {
return; return;
} }
} else if (!zstr(sofia_private->uuid)) { } else if (!zstr(sofia_private->uuid)) {
@ -734,6 +737,7 @@ void sofia_event_callback(nua_event_t event,
} }
} }
if (sofia_test_pflag(profile, PFLAG_AUTH_ALL) && tech_pvt && tech_pvt->key && sip) { if (sofia_test_pflag(profile, PFLAG_AUTH_ALL) && tech_pvt && tech_pvt->key && sip) {
sip_authorization_t const *authorization = NULL; sip_authorization_t const *authorization = NULL;
@ -1528,7 +1532,7 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t *thread, void
config_sofia(1, profile->name); config_sofia(1, profile->name);
} }
switch_core_destroy_memory_pool(&pool); sofia_profile_destroy(profile);
end: end:
switch_mutex_lock(mod_sofia_globals.mutex); 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; 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) void launch_sofia_profile_thread(sofia_profile_t *profile)
{ {
switch_thread_t *thread; switch_thread_t *thread;

View File

@ -3776,6 +3776,19 @@ char *sofia_glue_get_url_from_contact(char *buf, uint8_t to_dup)
return url; 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 *sofia_glue_find_profile__(const char *file, const char *func, int line, const char *key)
{ {
sofia_profile_t *profile; sofia_profile_t *profile;
@ -3789,10 +3802,7 @@ sofia_profile_t *sofia_glue_find_profile__(const char *file, const char *func, i
profile = NULL; profile = NULL;
goto done; goto done;
} }
if (switch_thread_rwlock_tryrdlock(profile->rwlock) != SWITCH_STATUS_SUCCESS) { if (sofia_glue_profile_rdlock__(file, func, line, profile) != 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
profile = NULL; profile = NULL;
} }
} else { } 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); switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_ERROR, "Profile %s is not in the hash\n", key);
#endif #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); switch_mutex_unlock(mod_sofia_globals.hash_mutex);
return profile; return profile;

View 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->status = SOFIA_GATEWAY_DOWN;
gateway_ptr->retry = 0; gateway_ptr->retry = 0;
if (!gateway_ptr->nh) if (!gateway_ptr->nh) {
sofia_reg_new_handle(gateway_ptr, now ? 1 : 0); sofia_reg_new_handle(gateway_ptr, now ? 1 : 0);
}
if (sofia_glue_check_nat(gateway_ptr->profile, gateway_ptr->register_proxy)) { 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); 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; gateway = NULL;
goto done; goto done;
} }
if (switch_thread_rwlock_tryrdlock(gateway->profile->rwlock) != SWITCH_STATUS_SUCCESS) { if (sofia_reg_gateway_rdlock__(file, func, line, gateway) != 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);
gateway = NULL; 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: done:
switch_mutex_unlock(mod_sofia_globals.hash_mutex); 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; 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) void sofia_reg_release_gateway__(const char *file, const char *func, int line, sofia_gateway_t *gateway)
{ {