diff --git a/src/include/switch_loadable_module.h b/src/include/switch_loadable_module.h index 9896725629..9a0fc6fd18 100644 --- a/src/include/switch_loadable_module.h +++ b/src/include/switch_loadable_module.h @@ -392,6 +392,11 @@ SWITCH_DECLARE(uint32_t) switch_core_codec_next_id(void); } +#define PROTECT_INTERFACE(_it) switch_thread_rwlock_rdlock(_it->parent->rwlock); switch_thread_rwlock_rdlock(_it->rwlock) +#define UNPROTECT_INTERFACE(_it) switch_thread_rwlock_unlock(_it->rwlock); switch_thread_rwlock_unlock(_it->parent->rwlock); _it = NULL + + + SWITCH_END_EXTERN_C #endif /* For Emacs: diff --git a/src/mod/dialplans/mod_dialplan_asterisk/mod_dialplan_asterisk.c b/src/mod/dialplans/mod_dialplan_asterisk/mod_dialplan_asterisk.c index 3f25227828..84d9aa4c87 100644 --- a/src/mod/dialplans/mod_dialplan_asterisk/mod_dialplan_asterisk.c +++ b/src/mod/dialplans/mod_dialplan_asterisk/mod_dialplan_asterisk.c @@ -39,12 +39,14 @@ SWITCH_MODULE_DEFINITION(mod_dialplan_asterisk, mod_dialplan_asterisk_load, NULL static switch_status_t exec_app(switch_core_session_t *session, char *app, char *arg) { const switch_application_interface_t *application_interface; + switch_status_t status = SWITCH_STATUS_FALSE; if ((application_interface = switch_loadable_module_get_application_interface(app))) { - return switch_core_session_exec(session, application_interface, arg); + status = switch_core_session_exec(session, application_interface, arg); + UNPROTECT_INTERFACE(application_interface); } - return SWITCH_STATUS_FALSE; + return status; } SWITCH_STANDARD_APP(dial_function) diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 0d34fe1d9f..6515680849 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -1168,9 +1168,9 @@ switch_status_t reconfig_sofia(sofia_profile_t *profile) } else if (!strcasecmp(val, "contact") || switch_true(val)) { profile->pflags |= PFLAG_MULTIREG; profile->pflags |= PFLAG_MULTIREG_CONTACT; - } else { + } else if (switch_true(val)) { profile->pflags &= ~PFLAG_MULTIREG; - profile->pflags &= ~PFLAG_MULTIREG_CONTACT; + //profile->pflags &= ~PFLAG_MULTIREG_CONTACT; } } else if (!strcasecmp(var, "supress-cng") || !strcasecmp(var, "suppress-cng")) { if (switch_true(val)) { @@ -1629,9 +1629,9 @@ switch_status_t config_sofia(int reload, char *profile_name) } else if (!strcasecmp(val, "contact") || switch_true(val)) { profile->pflags |= PFLAG_MULTIREG; profile->pflags |= PFLAG_MULTIREG_CONTACT; - } else { + } else if (switch_true(val)) { profile->pflags &= ~PFLAG_MULTIREG; - profile->pflags &= ~PFLAG_MULTIREG_CONTACT; + //profile->pflags &= ~PFLAG_MULTIREG_CONTACT; } } else if (!strcasecmp(var, "supress-cng") || !strcasecmp(var, "suppress-cng")) { if (switch_true(val)) { diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 112aea997f..2fe6be6eb6 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -2865,10 +2865,15 @@ int sofia_glue_init_sql(sofia_profile_t *profile) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Connected ODBC DSN: %s\n", profile->odbc_dsn); - if (switch_odbc_handle_exec(profile->master_odbc, "select hostname from sip_registrations", NULL) != SWITCH_ODBC_SUCCESS) { + test_sql = switch_mprintf("delete from sip_registrations where (contact like '%%TCP%%' " + "or status like '%%TCP%%' or status like '%%TLS%%') and hostname='%q'", + mod_sofia_globals.hostname); + + if (switch_odbc_handle_exec(profile->master_odbc, test_sql, NULL) != SWITCH_ODBC_SUCCESS) { switch_odbc_handle_exec(profile->master_odbc, "DROP TABLE sip_registrations", NULL); switch_odbc_handle_exec(profile->master_odbc, reg_sql, NULL); } + free(test_sql); test_sql = switch_mprintf("delete from sip_subscriptions where hostname='%q'", mod_sofia_globals.hostname); @@ -2898,13 +2903,18 @@ int sofia_glue_init_sql(sofia_profile_t *profile) #else switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ODBC IS NOT AVAILABLE!\n"); #endif - } else { + } else { if (!(profile->master_db = switch_core_db_open_file(profile->dbname))) { return 0; } - switch_core_db_test_reactive(profile->master_db, "select hostname from sip_registrations", "DROP TABLE sip_registrations", reg_sql); + test_sql = switch_mprintf("delete from sip_registrations where (contact like '%%TCP%%' " + "or status like '%%TCP%%' or status like '%%TLS%%') and hostname='%q'", + mod_sofia_globals.hostname); + switch_core_db_test_reactive(profile->master_db, test_sql, "DROP TABLE sip_registrations", reg_sql); + free(test_sql); + test_sql = switch_mprintf("delete from sip_subscriptions where hostname='%q'", mod_sofia_globals.hostname); switch_core_db_test_reactive(profile->master_db, test_sql, "DROP TABLE sip_subscriptions", sub_sql); free(test_sql); diff --git a/src/mod/formats/mod_local_stream/mod_local_stream.c b/src/mod/formats/mod_local_stream/mod_local_stream.c index 8e89d28c20..346f9b9597 100644 --- a/src/mod/formats/mod_local_stream/mod_local_stream.c +++ b/src/mod/formats/mod_local_stream/mod_local_stream.c @@ -249,6 +249,11 @@ static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void } done: + + if (fh.file_interface) { + switch_core_file_close(&fh); + } + source->ready = 0; switch_mutex_lock(globals.mutex); switch_core_hash_delete(globals.source_hash, source->name); diff --git a/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c b/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c index 88157fcdf6..edf050c8ef 100644 --- a/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c +++ b/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c @@ -2222,6 +2222,7 @@ static JSBool session_execute(JSContext * cx, JSObject * obj, uintN argc, jsval check_hangup_hook(jss, &ret); retval = JS_TRUE; } + UNPROTECT_INTERFACE(application_interface); } } diff --git a/src/switch_core_asr.c b/src/switch_core_asr.c index fbe13d0801..cd7833a904 100644 --- a/src/switch_core_asr.c +++ b/src/switch_core_asr.c @@ -64,6 +64,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_asr_open(switch_asr_handle_t *ah, ah->memory_pool = pool; } else { if ((status = switch_core_new_memory_pool(&ah->memory_pool)) != SWITCH_STATUS_SUCCESS) { + UNPROTECT_INTERFACE(ah->asr_interface); return status; } switch_set_flag(ah, SWITCH_ASR_FLAG_FREE_POOL); @@ -127,6 +128,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_asr_close(switch_asr_handle_t *ah, s switch_assert(ah != NULL); status = ah->asr_interface->asr_close(ah, flags); + UNPROTECT_INTERFACE(ah->asr_interface); if (switch_test_flag(ah, SWITCH_ASR_FLAG_FREE_POOL)) { switch_core_destroy_memory_pool(&ah->memory_pool); diff --git a/src/switch_core_codec.c b/src/switch_core_codec.c index b87a6503f5..637d855170 100644 --- a/src/switch_core_codec.c +++ b/src/switch_core_codec.c @@ -451,12 +451,15 @@ SWITCH_DECLARE(switch_status_t) switch_core_codec_init(switch_codec_t *codec, co implementation->init(codec, flags, codec_settings); switch_mutex_init(&codec->mutex, SWITCH_MUTEX_NESTED, codec->memory_pool); + return SWITCH_STATUS_SUCCESS; } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Codec %s Exists but not at the desired implementation. %dhz %dms\n", codec_name, rate, ms); } + UNPROTECT_INTERFACE(codec_interface); + return SWITCH_STATUS_NOTIMPL; } @@ -541,6 +544,9 @@ SWITCH_DECLARE(switch_status_t) switch_core_codec_destroy(switch_codec_t *codec) if (mutex) switch_mutex_lock(mutex); codec->implementation->destroy(codec); + + UNPROTECT_INTERFACE(codec->codec_interface); + memset(codec, 0, sizeof(*codec)); if (mutex) switch_mutex_unlock(mutex); diff --git a/src/switch_core_directory.c b/src/switch_core_directory.c index 3eedf4b231..6a719d37f9 100644 --- a/src/switch_core_directory.c +++ b/src/switch_core_directory.c @@ -49,6 +49,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_directory_open(switch_directory_hand dh->memory_pool = pool; } else { if ((status = switch_core_new_memory_pool(&dh->memory_pool)) != SWITCH_STATUS_SUCCESS) { + UNPROTECT_INTERFACE(dh->directory_interface); return status; } switch_set_flag(dh, SWITCH_DIRECTORY_FLAG_FREE_POOL); @@ -77,6 +78,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_directory_close(switch_directory_han switch_status_t status; status = dh->directory_interface->directory_close(dh); + UNPROTECT_INTERFACE(dh->directory_interface); if (switch_test_flag(dh, SWITCH_DIRECTORY_FLAG_FREE_POOL)) { switch_core_destroy_memory_pool(&dh->memory_pool); diff --git a/src/switch_core_file.c b/src/switch_core_file.c index 5614ffebae..b3b3677b9d 100644 --- a/src/switch_core_file.c +++ b/src/switch_core_file.c @@ -76,6 +76,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_perform_file_open(const char *file, fh->memory_pool = pool; } else { if ((status = switch_core_new_memory_pool(&fh->memory_pool)) != SWITCH_STATUS_SUCCESS) { + UNPROTECT_INTERFACE(fh->file_interface); return status; } switch_set_flag(fh, SWITCH_FILE_FLAG_FREE_POOL); @@ -98,9 +99,11 @@ SWITCH_DECLARE(switch_status_t) switch_core_perform_file_open(const char *file, } if ((status = fh->file_interface->file_open(fh, file_path)) != SWITCH_STATUS_SUCCESS) { + UNPROTECT_INTERFACE(fh->file_interface); return status; } + if ((flags & SWITCH_FILE_FLAG_READ)) { fh->native_rate = fh->samplerate; } else { @@ -281,6 +284,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_file_close(switch_file_handle_t *fh) switch_resample_destroy(&fh->resampler); + UNPROTECT_INTERFACE(fh->file_interface); + if (switch_test_flag(fh, SWITCH_FILE_FLAG_FREE_POOL)) { switch_core_destroy_memory_pool(&fh->memory_pool); } diff --git a/src/switch_core_session.c b/src/switch_core_session.c index debcb4a487..da22ddde8a 100644 --- a/src/switch_core_session.c +++ b/src/switch_core_session.c @@ -87,11 +87,13 @@ SWITCH_DECLARE(void) switch_core_session_hupall_matching_var(const char *var_nam if (val) { const char *this_val; session = (switch_core_session_t *) val; - switch_core_session_read_lock(session); - if ((this_val = switch_channel_get_variable(session->channel, var_name)) && (!strcmp(this_val, var_val))) { - switch_channel_hangup(switch_core_session_get_channel(session), cause); + if (switch_core_session_read_lock(session) == SWITCH_STATUS_SUCCESS) { + if (switch_channel_get_state(session->channel) < CS_HANGUP && + (this_val = switch_channel_get_variable(session->channel, var_name)) && (!strcmp(this_val, var_val))) { + switch_channel_hangup(session->channel, cause); + } + switch_core_session_rwunlock(session); } - switch_core_session_rwunlock(session); } } switch_mutex_unlock(runtime.throttle_mutex); @@ -826,8 +828,7 @@ SWITCH_DECLARE(void) switch_core_session_perform_destroy(switch_core_session_t * *session = NULL; switch_core_destroy_memory_pool(&pool); - switch_thread_rwlock_unlock(endpoint_interface->rwlock); - switch_thread_rwlock_unlock(endpoint_interface->parent->rwlock); + UNPROTECT_INTERFACE(endpoint_interface); } SWITCH_STANDARD_SCHED_FUNC(sch_heartbeat_callback) @@ -1006,6 +1007,7 @@ SWITCH_DECLARE(switch_core_session_t *) switch_core_session_request_uuid(const s uint32_t count = 0; int32_t sps = 0; + if (use_uuid && switch_core_hash_find(session_manager.session_table, use_uuid)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Duplicate UUID!\n"); return NULL; @@ -1016,6 +1018,8 @@ SWITCH_DECLARE(switch_core_session_t *) switch_core_session_request_uuid(const s return NULL; } + PROTECT_INTERFACE(endpoint_interface); + switch_mutex_lock(runtime.throttle_mutex); count = session_manager.session_count; sps = --runtime.sps; @@ -1023,17 +1027,16 @@ SWITCH_DECLARE(switch_core_session_t *) switch_core_session_request_uuid(const s if (sps <= 0) { //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Throttle Error!\n"); + UNPROTECT_INTERFACE(endpoint_interface); return NULL; } if ((count + 1) > session_manager.session_limit) { //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Over Session Limit!\n"); + UNPROTECT_INTERFACE(endpoint_interface); return NULL; } - switch_thread_rwlock_rdlock(endpoint_interface->parent->rwlock); - switch_thread_rwlock_rdlock(endpoint_interface->rwlock); - if (pool && *pool) { usepool = *pool; *pool = NULL; @@ -1114,7 +1117,9 @@ SWITCH_DECLARE(switch_core_session_t *) switch_core_session_request_by_name(cons return NULL; } + UNPROTECT_INTERFACE(endpoint_interface); return switch_core_session_request(endpoint_interface, pool); + } #ifndef SWITCH_PREFIX_DIR @@ -1195,6 +1200,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_execute_application(switch_c if (!application_interface->application_function) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No Function for %s\n", app); switch_channel_hangup(session->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); + UNPROTECT_INTERFACE(application_interface); return SWITCH_STATUS_FALSE; } @@ -1236,6 +1242,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_execute_application(switch_c switch_safe_free(expanded); } + UNPROTECT_INTERFACE(application_interface); + return SWITCH_STATUS_SUCCESS; } @@ -1282,11 +1290,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_exec(switch_core_session_t * switch_channel_set_variable(session->channel, SWITCH_CURRENT_APPLICATION_VARIABLE, application_interface->interface_name); - switch_thread_rwlock_rdlock(application_interface->parent->rwlock); - switch_thread_rwlock_rdlock(application_interface->rwlock); application_interface->application_function(session, arg); - switch_thread_rwlock_unlock(application_interface->rwlock); - switch_thread_rwlock_unlock(application_interface->parent->rwlock); if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_EXECUTE_COMPLETE) == SWITCH_STATUS_SUCCESS) { switch_channel_event_set_data(session->channel, event); diff --git a/src/switch_core_speech.c b/src/switch_core_speech.c index 9cab0865f5..8b2184abdb 100644 --- a/src/switch_core_speech.c +++ b/src/switch_core_speech.c @@ -66,6 +66,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_speech_open(switch_speech_handle_t * sh->memory_pool = pool; } else { if ((status = switch_core_new_memory_pool(&sh->memory_pool)) != SWITCH_STATUS_SUCCESS) { + UNPROTECT_INTERFACE(sh->speech_interface); return status; } switch_set_flag(sh, SWITCH_SPEECH_FLAG_FREE_POOL); @@ -139,6 +140,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_speech_close(switch_speech_handle_t { switch_status_t status = sh->speech_interface->speech_close(sh, flags); + UNPROTECT_INTERFACE(sh->speech_interface); + if (switch_test_flag(sh, SWITCH_SPEECH_FLAG_FREE_POOL)) { switch_core_destroy_memory_pool(&sh->memory_pool); } diff --git a/src/switch_core_state_machine.c b/src/switch_core_state_machine.c index 0bf7bd9cc5..dff6ef2d1b 100644 --- a/src/switch_core_state_machine.c +++ b/src/switch_core_state_machine.c @@ -91,8 +91,11 @@ static void switch_core_standard_on_routing(switch_core_session_t *session) } count++; - - if ((extension = dialplan_interface->hunt_function(session, dparg, NULL)) != 0) { + + extension = dialplan_interface->hunt_function(session, dparg, NULL); + UNPROTECT_INTERFACE(dialplan_interface); + + if (extension) { switch_channel_set_caller_extension(session->channel, extension); switch_channel_set_state(session->channel, CS_EXECUTE); goto end; diff --git a/src/switch_core_timer.c b/src/switch_core_timer.c index d9502bb8f2..0206028fb9 100644 --- a/src/switch_core_timer.c +++ b/src/switch_core_timer.c @@ -55,6 +55,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_timer_init(switch_timer_t *timer, co timer->memory_pool = pool; } else { if ((status = switch_core_new_memory_pool(&timer->memory_pool)) != SWITCH_STATUS_SUCCESS) { + UNPROTECT_INTERFACE(timer->timer_interface); return status; } switch_set_flag(timer, SWITCH_TIMER_FLAG_FREE_POOL); @@ -120,6 +121,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_timer_destroy(switch_timer_t *timer) } timer->timer_interface->timer_destroy(timer); + UNPROTECT_INTERFACE(timer->timer_interface); if (switch_test_flag(timer, SWITCH_TIMER_FLAG_FREE_POOL)) { switch_core_destroy_memory_pool(&timer->memory_pool); diff --git a/src/switch_ivr.c b/src/switch_ivr.c index b41ab18d4e..c52c50daf2 100644 --- a/src/switch_ivr.c +++ b/src/switch_ivr.c @@ -409,6 +409,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_parse_event(switch_core_session_t *se switch_channel_clear_flag(channel, CF_BROADCAST); } + UNPROTECT_INTERFACE(application_interface); } } } else if (cmd_hash == CMD_UNICAST) { diff --git a/src/switch_ivr_menu.c b/src/switch_ivr_menu.c index 38b1e857c6..f72257f641 100644 --- a/src/switch_ivr_menu.c +++ b/src/switch_ivr_menu.c @@ -477,6 +477,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_menu_execute(switch_core_session_t *s if ((application_interface = switch_loadable_module_get_application_interface(app_name))) { switch_core_session_exec(session, application_interface, app_arg); + UNPROTECT_INTERFACE(application_interface); status = SWITCH_STATUS_SUCCESS; } } diff --git a/src/switch_ivr_originate.c b/src/switch_ivr_originate.c index 88cc6d564e..328c9eed49 100644 --- a/src/switch_ivr_originate.c +++ b/src/switch_ivr_originate.c @@ -115,6 +115,7 @@ static void *SWITCH_THREAD_FUNC collect_thread_run(switch_thread_t *thread, void if ((application_interface = switch_loadable_module_get_application_interface(app_name)) == 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Application %s\n", app_name); switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); + UNPROTECT_INTERFACE(application_interface); goto wbreak; } diff --git a/src/switch_ivr_play_say.c b/src/switch_ivr_play_say.c index 06004f2e48..e20d49b5d2 100644 --- a/src/switch_ivr_play_say.c +++ b/src/switch_ivr_play_say.c @@ -293,6 +293,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_phrase_macro(switch_core_session_t *s if ((app = switch_loadable_module_get_application_interface(cmd)) != NULL) { status = switch_core_session_exec(session, app, cmd_args); + UNPROTECT_INTERFACE(app); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Application %s\n", cmd); } diff --git a/src/switch_loadable_module.c b/src/switch_loadable_module.c index ad448ad572..1dcb84dacb 100644 --- a/src/switch_loadable_module.c +++ b/src/switch_loadable_module.c @@ -455,6 +455,8 @@ static switch_status_t switch_loadable_module_unprocess(switch_loadable_module_t switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Deleting Codec '%s' (%s) %dhz %dms\n", impl->iananame, ptr->interface_name, impl->actual_samples_per_second, impl->microseconds_per_packet / 1000); + switch_core_session_hupall_matching_var("read_codec", impl->iananame, SWITCH_CAUSE_SYSTEM_SHUTDOWN); + switch_core_session_hupall_matching_var("write_codec", impl->iananame, SWITCH_CAUSE_SYSTEM_SHUTDOWN); if (switch_core_hash_find(loadable_modules.codec_hash, impl->iananame)) { switch_core_hash_delete(loadable_modules.codec_hash, impl->iananame); } @@ -560,6 +562,15 @@ static switch_status_t switch_loadable_module_unprocess(switch_loadable_module_t for (ptr = old_module->module_interface->file_interface; ptr; ptr = ptr->next) { if (ptr->interface_name) { int i; + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Write lock interface '%s' to wait for existing references.\n", ptr->interface_name); + + if (switch_thread_rwlock_trywrlock_timeout(ptr->rwlock, 10) == SWITCH_STATUS_SUCCESS) { + switch_thread_rwlock_unlock(ptr->rwlock); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Giving up waiting for existing references.\n"); + } + for (i = 0; ptr->extens[i]; i++) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Deleting File Format '%s'\n", ptr->extens[i]); if (switch_event_create(&event, SWITCH_EVENT_MODULE_UNLOAD) == SWITCH_STATUS_SUCCESS) { @@ -577,7 +588,17 @@ static switch_status_t switch_loadable_module_unprocess(switch_loadable_module_t const switch_speech_interface_t *ptr; for (ptr = old_module->module_interface->speech_interface; ptr; ptr = ptr->next) { + if (ptr->interface_name) { + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Write lock interface '%s' to wait for existing references.\n", ptr->interface_name); + + if (switch_thread_rwlock_trywrlock_timeout(ptr->rwlock, 10) == SWITCH_STATUS_SUCCESS) { + switch_thread_rwlock_unlock(ptr->rwlock); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Giving up waiting for existing references.\n"); + } + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Deleting Speech interface '%s'\n", ptr->interface_name); if (switch_event_create(&event, SWITCH_EVENT_MODULE_UNLOAD) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "speech"); @@ -594,6 +615,15 @@ static switch_status_t switch_loadable_module_unprocess(switch_loadable_module_t for (ptr = old_module->module_interface->asr_interface; ptr; ptr = ptr->next) { if (ptr->interface_name) { + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Write lock interface '%s' to wait for existing references.\n", ptr->interface_name); + + if (switch_thread_rwlock_trywrlock_timeout(ptr->rwlock, 10) == SWITCH_STATUS_SUCCESS) { + switch_thread_rwlock_unlock(ptr->rwlock); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Giving up waiting for existing references.\n"); + } + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Deleting Asr interface '%s'\n", ptr->interface_name); if (switch_event_create(&event, SWITCH_EVENT_MODULE_UNLOAD) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "asr"); @@ -610,6 +640,15 @@ static switch_status_t switch_loadable_module_unprocess(switch_loadable_module_t for (ptr = old_module->module_interface->directory_interface; ptr; ptr = ptr->next) { if (ptr->interface_name) { + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Write lock interface '%s' to wait for existing references.\n", ptr->interface_name); + + if (switch_thread_rwlock_trywrlock_timeout(ptr->rwlock, 10) == SWITCH_STATUS_SUCCESS) { + switch_thread_rwlock_unlock(ptr->rwlock); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Giving up waiting for existing references.\n"); + } + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Deleting Directory interface '%s'\n", ptr->interface_name); if (switch_event_create(&event, SWITCH_EVENT_MODULE_UNLOAD) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "directory"); @@ -627,6 +666,14 @@ static switch_status_t switch_loadable_module_unprocess(switch_loadable_module_t for (ptr = old_module->module_interface->chat_interface; ptr; ptr = ptr->next) { if (ptr->interface_name) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Write lock interface '%s' to wait for existing references.\n", ptr->interface_name); + + if (switch_thread_rwlock_trywrlock_timeout(ptr->rwlock, 10) == SWITCH_STATUS_SUCCESS) { + switch_thread_rwlock_unlock(ptr->rwlock); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Giving up waiting for existing references.\n"); + } + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Deleting Chat interface '%s'\n", ptr->interface_name); if (switch_event_create(&event, SWITCH_EVENT_MODULE_UNLOAD) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "chat"); @@ -643,6 +690,13 @@ static switch_status_t switch_loadable_module_unprocess(switch_loadable_module_t for (ptr = old_module->module_interface->say_interface; ptr; ptr = ptr->next) { if (ptr->interface_name) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Write lock interface '%s' to wait for existing references.\n", ptr->interface_name); + + if (switch_thread_rwlock_trywrlock_timeout(ptr->rwlock, 10) == SWITCH_STATUS_SUCCESS) { + switch_thread_rwlock_unlock(ptr->rwlock); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Giving up waiting for existing references.\n"); + } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Deleting Say interface '%s'\n", ptr->interface_name); if (switch_event_create(&event, SWITCH_EVENT_MODULE_UNLOAD) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "say"); @@ -913,6 +967,7 @@ SWITCH_DECLARE(switch_status_t) switch_loadable_module_unload_module(char *dir, switch_mutex_unlock(loadable_modules.mutex); if (force) { + switch_yield(1000000); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "PHEW!\n"); } @@ -1239,8 +1294,12 @@ SWITCH_DECLARE(switch_endpoint_interface_t *) switch_loadable_module_get_endpoin switch_mutex_lock(loadable_modules.mutex); ptr = switch_core_hash_find(loadable_modules.endpoint_hash, name); + if (ptr) { + PROTECT_INTERFACE(ptr); + } switch_mutex_unlock(loadable_modules.mutex); + return ptr; } @@ -1263,57 +1322,41 @@ SWITCH_DECLARE(switch_codec_interface_t *) switch_loadable_module_get_codec_inte } } switch_mutex_unlock(loadable_modules.mutex); + + if (codec) { + PROTECT_INTERFACE(codec); + } + return codec; } -SWITCH_DECLARE(switch_dialplan_interface_t *) switch_loadable_module_get_dialplan_interface(const char *name) -{ - return switch_core_hash_find_locked(loadable_modules.dialplan_hash, name, loadable_modules.mutex); -} +#define HASH_FUNC(_kind_) SWITCH_DECLARE(switch_##_kind_##_interface_t *) switch_loadable_module_get_##_kind_##_interface(const char *name) \ + { \ + switch_##_kind_##_interface_t *i; \ + if ((i = switch_core_hash_find_locked(loadable_modules._kind_##_hash, name, loadable_modules.mutex))) { \ + PROTECT_INTERFACE(i); \ + } \ + return i; \ + } + +HASH_FUNC(dialplan) +HASH_FUNC(timer) +HASH_FUNC(application) +HASH_FUNC(api) +HASH_FUNC(file) +HASH_FUNC(speech) +HASH_FUNC(asr) +HASH_FUNC(directory) -SWITCH_DECLARE(switch_timer_interface_t *) switch_loadable_module_get_timer_interface(const char *name) -{ - return switch_core_hash_find_locked(loadable_modules.timer_hash, name, loadable_modules.mutex); -} - -SWITCH_DECLARE(switch_application_interface_t *) switch_loadable_module_get_application_interface(const char *name) -{ - return switch_core_hash_find_locked(loadable_modules.application_hash, name, loadable_modules.mutex); -} - -SWITCH_DECLARE(switch_api_interface_t *) switch_loadable_module_get_api_interface(const char *name) -{ - return switch_core_hash_find_locked(loadable_modules.api_hash, name, loadable_modules.mutex); -} - -SWITCH_DECLARE(switch_file_interface_t *) switch_loadable_module_get_file_interface(const char *name) -{ - return switch_core_hash_find_locked(loadable_modules.file_hash, name, loadable_modules.mutex); -} - -SWITCH_DECLARE(switch_speech_interface_t *) switch_loadable_module_get_speech_interface(const char *name) -{ - return switch_core_hash_find_locked(loadable_modules.speech_hash, name, loadable_modules.mutex); -} - -SWITCH_DECLARE(switch_asr_interface_t *) switch_loadable_module_get_asr_interface(const char *name) -{ - return switch_core_hash_find_locked(loadable_modules.asr_hash, name, loadable_modules.mutex); -} - -SWITCH_DECLARE(switch_directory_interface_t *) switch_loadable_module_get_directory_interface(const char *name) -{ - return switch_core_hash_find_locked(loadable_modules.directory_hash, name, loadable_modules.mutex); -} SWITCH_DECLARE(switch_chat_interface_t *) switch_loadable_module_get_chat_interface(const char *name) { - return switch_core_hash_find_locked(loadable_modules.chat_hash, name, loadable_modules.mutex); + return switch_core_hash_find_locked(loadable_modules.chat_hash, name, loadable_modules.mutex); } SWITCH_DECLARE(switch_say_interface_t *) switch_loadable_module_get_say_interface(const char *name) { - return switch_core_hash_find_locked(loadable_modules.say_hash, name, loadable_modules.mutex); + return switch_core_hash_find_locked(loadable_modules.say_hash, name, loadable_modules.mutex); } SWITCH_DECLARE(switch_management_interface_t *) switch_loadable_module_get_management_interface(const char *relative_oid) @@ -1472,13 +1515,10 @@ SWITCH_DECLARE(switch_status_t) switch_api_execute(const char *cmd, const char * if (cmd && (api = switch_loadable_module_get_api_interface(cmd)) != 0) { - switch_thread_rwlock_rdlock(api->parent->rwlock); - switch_thread_rwlock_rdlock(api->rwlock); if ((status = api->function(arg, session, stream)) != SWITCH_STATUS_SUCCESS) { stream->write_function(stream, "COMMAND RETURNED ERROR!\n"); } - switch_thread_rwlock_unlock(api->rwlock); - switch_thread_rwlock_unlock(api->parent->rwlock); + UNPROTECT_INTERFACE(api); } else { status = SWITCH_STATUS_FALSE; stream->write_function(stream, "INVALID COMMAND!\n");