[Freeswitch-svn] [commit] r5078 - in freeswitch/trunk/src: . include mod/applications/mod_commands mod/endpoints/mod_sofia

Freeswitch SVN anthm at freeswitch.org
Thu May 3 12:28:24 EDT 2007


Author: anthm
Date: Thu May  3 12:28:23 2007
New Revision: 5078

Modified:
   freeswitch/trunk/src/include/switch_core.h
   freeswitch/trunk/src/include/switch_loadable_module.h
   freeswitch/trunk/src/include/switch_types.h
   freeswitch/trunk/src/mod/applications/mod_commands/mod_commands.c
   freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c
   freeswitch/trunk/src/switch_core_hash.c
   freeswitch/trunk/src/switch_event.c
   freeswitch/trunk/src/switch_loadable_module.c

Log:
general improvements

Modified: freeswitch/trunk/src/include/switch_core.h
==============================================================================
--- freeswitch/trunk/src/include/switch_core.h	(original)
+++ freeswitch/trunk/src/include/switch_core.h	Thu May  3 12:28:23 2007
@@ -819,6 +819,17 @@
 SWITCH_DECLARE(switch_status_t) switch_core_hash_insert(switch_hash_t * hash, const char *key, const void *data);
 
 /*! 
+  \brief Insert data into a hash
+  \param hash the hash to add data to
+  \param key the name of the key to add the data to
+  \param data the data to add
+  \param mutex optional mutex to lock
+  \return SWITCH_STATUS_SUCCESS if the data is added
+  \note the string key must be a constant or a dynamic string
+*/
+SWITCH_DECLARE(switch_status_t) switch_core_hash_insert_locked(switch_hash_t * hash, const char *key, const void *data, switch_mutex_t *mutex);
+
+/*! 
   \brief Insert data into a hash with dynamicly allocated key name
   \param hash the hash to add data to
   \param key the name of the key to add the data to
@@ -828,6 +839,16 @@
 SWITCH_DECLARE(switch_status_t) switch_core_hash_insert_dup(switch_hash_t * hash, const char *key, const void *data);
 
 /*! 
+  \brief Insert data into a hash with dynamicly allocated key name
+  \param hash the hash to add data to
+  \param key the name of the key to add the data to
+  \param data the data to add
+  \param mutex optional mutex to lock
+  \return SWITCH_STATUS_SUCCESS if the data is added
+*/
+SWITCH_DECLARE(switch_status_t) switch_core_hash_insert_dup_locked(switch_hash_t * hash, const char *key, const void *data, switch_mutex_t *mutex);
+
+/*! 
   \brief Delete data from a hash based on desired key
   \param hash the hash to delete from
   \param key the key from which to delete the data
@@ -836,12 +857,32 @@
 SWITCH_DECLARE(switch_status_t) switch_core_hash_delete(switch_hash_t * hash, const char *key);
 
 /*! 
+  \brief Delete data from a hash based on desired key
+  \param hash the hash to delete from
+  \param key the key from which to delete the data
+  \param mutex optional mutex to lock
+  \return SWITCH_STATUS_SUCCESS if the data is deleted
+*/
+SWITCH_DECLARE(switch_status_t) switch_core_hash_delete_locked(switch_hash_t * hash, const char *key, switch_mutex_t *mutex);
+
+/*! 
   \brief Retrieve data from a given hash
   \param hash the hash to retrieve from
   \param key the key to retrieve
   \return a pointer to the data held in the key
 */
 SWITCH_DECLARE(void *) switch_core_hash_find(switch_hash_t * hash, const char *key);
+
+
+/*! 
+  \brief Retrieve data from a given hash
+  \param hash the hash to retrieve from
+  \param key the key to retrieve
+  \param mutex optional mutex to lock
+  \return a pointer to the data held in the key
+*/
+SWITCH_DECLARE(void *) switch_core_hash_find_locked(switch_hash_t * hash, const char *key, switch_mutex_t *mutex);
+
 ///\}
 
 ///\defgroup timer Timer Functions

Modified: freeswitch/trunk/src/include/switch_loadable_module.h
==============================================================================
--- freeswitch/trunk/src/include/switch_loadable_module.h	(original)
+++ freeswitch/trunk/src/include/switch_loadable_module.h	Thu May  3 12:28:23 2007
@@ -228,15 +228,24 @@
 */
 SWITCH_DECLARE(switch_status_t) switch_api_execute(char *cmd, char *arg, switch_core_session_t *session, switch_stream_handle_t *stream);
 
-
-
 /*!
   \brief Load a module
   \param dir the directory where the module resides
   \param fname the file name of the module
+  \param runtime option to start the runtime thread if it exists
+  \param err pointer to error message
+  \return the status
+*/
+SWITCH_DECLARE(switch_status_t) switch_loadable_module_load_module(char *dir, char *fname, switch_bool_t runtime, const char **err);
+
+/*!
+  \brief Unoad a module
+  \param dir the directory where the module resides
+  \param fname the file name of the module
+  \param err pointer to error message
   \return the status
 */
-SWITCH_DECLARE(switch_status_t) switch_loadable_module_load_module(char *dir, char *fname, switch_bool_t runtime);
+SWITCH_DECLARE(switch_status_t) switch_loadable_module_unload_module(char *dir, char *fname, const char **err);
 
 /* Prototypes of module interface functions */
 

Modified: freeswitch/trunk/src/include/switch_types.h
==============================================================================
--- freeswitch/trunk/src/include/switch_types.h	(original)
+++ freeswitch/trunk/src/include/switch_types.h	Thu May  3 12:28:23 2007
@@ -420,6 +420,7 @@
 	SWITCH_STATUS_MORE_DATA - Need More Data
 	SWITCH_STATUS_NOTFOUND  - Not Found
 	SWITCH_STATUS_UNLOAD    - Unload
+	SWITCH_STATUS_NOUNLOAD  - Never Unload
 </pre>
  */
 typedef enum {
@@ -438,7 +439,8 @@
 	SWITCH_STATUS_SOCKERR,
 	SWITCH_STATUS_MORE_DATA,
 	SWITCH_STATUS_NOTFOUND,
-	SWITCH_STATUS_UNLOAD
+	SWITCH_STATUS_UNLOAD,
+	SWITCH_STATUS_NOUNLOAD
 } switch_status_t;
 
 
@@ -816,6 +818,7 @@
 	SWITCH_EVENT_NOTALK				- Not Talking Detected
 	SWITCH_EVENT_SESSION_CRASH		- Session Crashed
 	SWITCH_EVENT_MODULE_LOAD		- Module was loaded
+	SWITCH_EVENT_MODULE_UNLOAD		- Module was unloaded
 	SWITCH_EVENT_DTMF				- DTMF was sent
 	SWITCH_EVENT_MESSAGE			- A Basic Message
 	SWITCH_EVENT_PRESENCE_IN		- Presence in
@@ -863,6 +866,7 @@
 	SWITCH_EVENT_NOTALK,
 	SWITCH_EVENT_SESSION_CRASH,
 	SWITCH_EVENT_MODULE_LOAD,
+	SWITCH_EVENT_MODULE_UNLOAD,
 	SWITCH_EVENT_DTMF,
 	SWITCH_EVENT_MESSAGE,
 	SWITCH_EVENT_PRESENCE_IN,

Modified: freeswitch/trunk/src/mod/applications/mod_commands/mod_commands.c
==============================================================================
--- freeswitch/trunk/src/mod/applications/mod_commands/mod_commands.c	(original)
+++ freeswitch/trunk/src/mod/applications/mod_commands/mod_commands.c	Thu May  3 12:28:23 2007
@@ -46,6 +46,7 @@
 static switch_api_interface_t pause_api_interface;
 static switch_api_interface_t transfer_api_interface;
 static switch_api_interface_t load_api_interface;
+static switch_api_interface_t unload_api_interface;
 static switch_api_interface_t reload_api_interface;
 static switch_api_interface_t kill_api_interface;
 static switch_api_interface_t originate_api_interface;
@@ -150,6 +151,7 @@
 
 static switch_status_t load_function(char *mod, switch_core_session_t *session, switch_stream_handle_t *stream)
 {
+	const char *err;
 
 	if (session) {
 		return SWITCH_STATUS_FALSE;
@@ -160,10 +162,32 @@
 		return SWITCH_STATUS_SUCCESS;
 	}
 
-	if (switch_loadable_module_load_module((char *) SWITCH_GLOBAL_dirs.mod_dir, (char *) mod, SWITCH_TRUE) == SWITCH_STATUS_SUCCESS) {
+	if (switch_loadable_module_load_module((char *) SWITCH_GLOBAL_dirs.mod_dir, (char *) mod, SWITCH_TRUE, &err) == SWITCH_STATUS_SUCCESS) {
 		stream->write_function(stream, "OK\n");
 	} else {
-		stream->write_function(stream, "ERROR\n");
+		stream->write_function(stream, "ERROR [%s]\n", err);
+	}
+
+	return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t unload_function(char *mod, switch_core_session_t *session, switch_stream_handle_t *stream)
+{
+	const char *err;
+
+	if (session) {
+		return SWITCH_STATUS_FALSE;
+	}
+
+	if (switch_strlen_zero(mod)) {
+		stream->write_function(stream, "USAGE: %s\n", unload_api_interface.syntax);
+		return SWITCH_STATUS_SUCCESS;
+	}
+
+	if (switch_loadable_module_unload_module((char *) SWITCH_GLOBAL_dirs.mod_dir, (char *) mod, &err) == SWITCH_STATUS_SUCCESS) {
+		stream->write_function(stream, "OK\n");
+	} else {
+		stream->write_function(stream, "ERROR [%s]\n", err);
 	}
 
 	return SWITCH_STATUS_SUCCESS;
@@ -1221,12 +1245,20 @@
 	/*.next */ &transfer_api_interface
 };
 
+static switch_api_interface_t unload_api_interface = {
+	/*.interface_name */ "unload",
+	/*.desc */ "Unoad Module",
+	/*.function */ unload_function,
+	/*.syntax */ "<mod_name>",
+	/*.next */ &load_api_interface
+};
+
 static switch_api_interface_t reload_api_interface = {
 	/*.interface_name */ "reloadxml",
 	/*.desc */ "Reload XML",
 	/*.function */ reload_function,
 	/*.syntax */ "",
-	/*.next */ &load_api_interface,
+	/*.next */ &unload_api_interface,
 
 };
 
@@ -1263,7 +1295,7 @@
 	*module_interface = &mod_commands_module_interface;
 
 	/* indicate that the module should continue to be loaded */
-	return SWITCH_STATUS_SUCCESS;
+	return SWITCH_STATUS_NOUNLOAD;
 }
 
 /* For Emacs:

Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c	(original)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c	Thu May  3 12:28:23 2007
@@ -1565,11 +1565,14 @@
 #endif
 
 #ifdef SWITCH_HAVE_ODBC
-	return profile->master_odbc ? 1 : 0;
-#else
-	return 1;
+	if (profile->odbc_dsn) {
+		return profile->master_odbc ? 1 : 0;
+	}
 #endif
 
+	return profile->master_db ? 1: 0;
+
+
 }
 
 void sofia_glue_sql_close(sofia_profile_t *profile)

Modified: freeswitch/trunk/src/switch_core_hash.c
==============================================================================
--- freeswitch/trunk/src/switch_core_hash.c	(original)
+++ freeswitch/trunk/src/switch_core_hash.c	Thu May  3 12:28:23 2007
@@ -57,19 +57,83 @@
 	return SWITCH_STATUS_SUCCESS;
 }
 
+SWITCH_DECLARE(switch_status_t) switch_core_hash_insert_dup_locked(switch_hash_t * hash, const char *key, const void *data, switch_mutex_t *mutex)
+{
+	if (mutex) {
+        switch_mutex_lock(mutex);
+    }
+
+	apr_hash_set(hash, switch_core_strdup(apr_hash_pool_get(hash), key), APR_HASH_KEY_STRING, data);
+
+	if (mutex) {
+        switch_mutex_unlock(mutex);
+    }
+
+
+	return SWITCH_STATUS_SUCCESS;
+}
+
 SWITCH_DECLARE(switch_status_t) switch_core_hash_insert(switch_hash_t * hash, const char *key, const void *data)
 {
 	apr_hash_set(hash, key, APR_HASH_KEY_STRING, data);
 	return SWITCH_STATUS_SUCCESS;
 }
 
+SWITCH_DECLARE(switch_status_t) switch_core_hash_insert_locked(switch_hash_t * hash, const char *key, const void *data, switch_mutex_t *mutex)
+{
+	if (mutex) {
+        switch_mutex_lock(mutex);
+    }
+	
+	apr_hash_set(hash, key, APR_HASH_KEY_STRING, data);
+
+	if (mutex) {
+        switch_mutex_unlock(mutex);
+    }	
+
+	return SWITCH_STATUS_SUCCESS;
+}
+
 SWITCH_DECLARE(switch_status_t) switch_core_hash_delete(switch_hash_t * hash, const char *key)
 {
 	apr_hash_set(hash, key, APR_HASH_KEY_STRING, NULL);
 	return SWITCH_STATUS_SUCCESS;
 }
 
+SWITCH_DECLARE(switch_status_t) switch_core_hash_delete_locked(switch_hash_t * hash, const char *key, switch_mutex_t *mutex)
+{
+	if (mutex) {
+        switch_mutex_lock(mutex);
+    }
+	
+	apr_hash_set(hash, key, APR_HASH_KEY_STRING, NULL);
+
+	if (mutex) {
+        switch_mutex_unlock(mutex);
+    }
+
+	return SWITCH_STATUS_SUCCESS;
+}
+
+
 SWITCH_DECLARE(void *) switch_core_hash_find(switch_hash_t * hash, const char *key)
 {
 	return apr_hash_get(hash, key, APR_HASH_KEY_STRING);
 }
+
+SWITCH_DECLARE(void *) switch_core_hash_find_locked(switch_hash_t * hash, const char *key, switch_mutex_t *mutex)
+{
+	void *val;
+
+	if (mutex) {
+		switch_mutex_lock(mutex);
+	}
+
+	val = apr_hash_get(hash, key, APR_HASH_KEY_STRING);
+
+	if (mutex) {
+		switch_mutex_unlock(mutex);
+	}
+
+	return val;
+}

Modified: freeswitch/trunk/src/switch_event.c
==============================================================================
--- freeswitch/trunk/src/switch_event.c	(original)
+++ freeswitch/trunk/src/switch_event.c	Thu May  3 12:28:23 2007
@@ -121,6 +121,7 @@
 	"NOTALK",
 	"SESSION_CRASH",
 	"MODULE_LOAD",
+	"MODULE_UNLOAD",
 	"DTMF",
 	"MESSAGE",
 	"PRESENCE_IN",

Modified: freeswitch/trunk/src/switch_loadable_module.c
==============================================================================
--- freeswitch/trunk/src/switch_loadable_module.c	(original)
+++ freeswitch/trunk/src/switch_loadable_module.c	Thu May  3 12:28:23 2007
@@ -41,12 +41,15 @@
 #include <apr_file_io.h>
 
 struct switch_loadable_module {
+	char *key;
 	char *filename;
+	int perm;
 	const switch_loadable_module_interface_t *module_interface;
 	void *lib;
 	switch_module_load_t switch_module_load;
 	switch_module_runtime_t switch_module_runtime;
 	switch_module_shutdown_t switch_module_shutdown;
+	switch_memory_pool_t *pool;
 };
 
 struct switch_loadable_module_container {
@@ -64,10 +67,12 @@
 	switch_hash_t *chat_hash;
 	switch_hash_t *say_hash;
 	switch_hash_t *management_hash;
+	switch_mutex_t *mutex;
 	switch_memory_pool_t *pool;
 };
 
 static struct switch_loadable_module_container loadable_modules;
+static void do_shutdown(switch_loadable_module_t *module);
 
 static void *switch_loadable_module_exec(switch_thread_t * thread, void *obj)
 {
@@ -102,6 +107,7 @@
 	void *val;
 	switch_loadable_module_t *module;
 
+	switch_mutex_lock(loadable_modules.mutex);
 	for (hi = switch_hash_first(loadable_modules.pool, loadable_modules.module_hash); hi; hi = switch_hash_next(hi)) {
 		switch_hash_this(hi, NULL, NULL, &val);
 		module = (switch_loadable_module_t *) val;
@@ -111,12 +117,16 @@
 			switch_core_launch_thread(switch_loadable_module_exec, module, loadable_modules.pool);
 		}
 	}
+	switch_mutex_unlock(loadable_modules.mutex);
 }
 
 static switch_status_t switch_loadable_module_process(char *key, switch_loadable_module_t *new_module)
 {
 	switch_event_t *event;
 
+	new_module->key = switch_core_strdup(new_module->pool, key);
+	
+	switch_mutex_lock(loadable_modules.mutex);
 	switch_core_hash_insert(loadable_modules.module_hash, key, new_module);
 
 	if (new_module->module_interface->endpoint_interface) {
@@ -380,11 +390,252 @@
 		}
 	}
 
+	switch_mutex_unlock(loadable_modules.mutex);
+	return SWITCH_STATUS_SUCCESS;
+
+}
+
+
+static switch_status_t switch_loadable_module_unprocess(switch_loadable_module_t *old_module)
+{
+	switch_event_t *event;
+
+	switch_mutex_lock(loadable_modules.mutex);
+	switch_core_hash_delete(loadable_modules.module_hash, old_module->key);
+
+	if (old_module->module_interface->endpoint_interface) {
+		const switch_endpoint_interface_t *ptr;
+		for (ptr = old_module->module_interface->endpoint_interface; ptr; ptr = ptr->next) {
+			if (ptr->interface_name) {
+				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Deleting Endpoint '%s'\n", ptr->interface_name);
+				switch_core_hash_delete(loadable_modules.endpoint_hash, ptr->interface_name);
+			}
+		}
+	}
+
+	if (old_module->module_interface->codec_interface) {
+		const switch_codec_implementation_t *impl;
+		const switch_codec_interface_t *ptr;
+
+		for (ptr = old_module->module_interface->codec_interface; ptr; ptr = ptr->next) {
+			if (ptr->interface_name) {
+				unsigned load_interface = 1;
+				for (impl = ptr->implementations; impl; impl = impl->next) {
+					if (!impl->iananame) {
+						load_interface = 0;
+						break;
+					}
+				}
+				if (load_interface) {
+					for (impl = ptr->implementations; impl; impl = impl->next) {
+						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE,
+										  "Deleting Codec '%s' (%s) %dhz %dms\n",
+										  impl->iananame, ptr->interface_name, impl->samples_per_second, impl->microseconds_per_frame / 1000);
+						if (switch_core_hash_find(loadable_modules.codec_hash, impl->iananame)) {
+							switch_core_hash_delete(loadable_modules.codec_hash, impl->iananame);
+						}
+					}
+					if (switch_event_create(&event, SWITCH_EVENT_MODULE_UNLOAD) == SWITCH_STATUS_SUCCESS) {
+						switch_event_add_header(event, SWITCH_STACK_BOTTOM, "type", "codec");
+						switch_event_add_header(event, SWITCH_STACK_BOTTOM, "name", "%s", ptr->interface_name);
+						switch_event_fire(&event);
+					}
+				}
+			}
+		}
+	}
+
+	if (old_module->module_interface->dialplan_interface) {
+		const switch_dialplan_interface_t *ptr;
+
+		for (ptr = old_module->module_interface->dialplan_interface; ptr; ptr = ptr->next) {
+			if (ptr->interface_name) {
+				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Deleting Dialplan '%s'\n", ptr->interface_name);
+				if (switch_event_create(&event, SWITCH_EVENT_MODULE_UNLOAD) == SWITCH_STATUS_SUCCESS) {
+					switch_event_add_header(event, SWITCH_STACK_BOTTOM, "type", "dialplan");
+					switch_event_add_header(event, SWITCH_STACK_BOTTOM, "name", "%s", ptr->interface_name);
+					switch_event_fire(&event);
+				}
+				switch_core_hash_delete(loadable_modules.dialplan_hash, ptr->interface_name);
+			}
+		}
+	}
+
+	if (old_module->module_interface->timer_interface) {
+		const switch_timer_interface_t *ptr;
+
+		for (ptr = old_module->module_interface->timer_interface; ptr; ptr = ptr->next) {
+			if (ptr->interface_name) {
+				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Deleting Timer '%s'\n", ptr->interface_name);
+				if (switch_event_create(&event, SWITCH_EVENT_MODULE_UNLOAD) == SWITCH_STATUS_SUCCESS) {
+					switch_event_add_header(event, SWITCH_STACK_BOTTOM, "type", "timer");
+					switch_event_add_header(event, SWITCH_STACK_BOTTOM, "name", "%s", ptr->interface_name);
+					switch_event_fire(&event);
+				}
+				switch_core_hash_delete(loadable_modules.timer_hash, ptr->interface_name);
+			}
+		}
+	}
+
+	if (old_module->module_interface->application_interface) {
+		const switch_application_interface_t *ptr;
+
+		for (ptr = old_module->module_interface->application_interface; ptr; ptr = ptr->next) {
+			if (ptr->interface_name) {
+				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Deleting Application '%s'\n", ptr->interface_name);
+				if (switch_event_create(&event, SWITCH_EVENT_MODULE_UNLOAD) == SWITCH_STATUS_SUCCESS) {
+					switch_event_add_header(event, SWITCH_STACK_BOTTOM, "type", "application");
+					switch_event_add_header(event, SWITCH_STACK_BOTTOM, "name", "%s", ptr->interface_name);
+					switch_event_add_header(event, SWITCH_STACK_BOTTOM, "description", "%s", switch_str_nil(ptr->short_desc));
+					switch_event_add_header(event, SWITCH_STACK_BOTTOM, "syntax", "%s", switch_str_nil(ptr->syntax));
+					switch_event_fire(&event);
+				}
+				switch_core_hash_delete(loadable_modules.application_hash, ptr->interface_name);
+			}
+		}
+	}
+
+	if (old_module->module_interface->api_interface) {
+		const switch_api_interface_t *ptr;
+
+		for (ptr = old_module->module_interface->api_interface; ptr; ptr = ptr->next) {
+			if (ptr->interface_name) {
+				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Deleting API Function '%s'\n", ptr->interface_name);
+				if (switch_event_create(&event, SWITCH_EVENT_MODULE_UNLOAD) == SWITCH_STATUS_SUCCESS) {
+					switch_event_add_header(event, SWITCH_STACK_BOTTOM, "type", "api");
+					switch_event_add_header(event, SWITCH_STACK_BOTTOM, "name", "%s", ptr->interface_name);
+					switch_event_add_header(event, SWITCH_STACK_BOTTOM, "description", "%s", switch_str_nil(ptr->desc));
+					switch_event_add_header(event, SWITCH_STACK_BOTTOM, "syntax", "%s", switch_str_nil(ptr->syntax));
+					switch_event_fire(&event);
+				}
+				switch_core_hash_delete(loadable_modules.api_hash, ptr->interface_name);
+			}
+		}
+	}
+
+	if (old_module->module_interface->file_interface) {
+		const switch_file_interface_t *ptr;
+
+		for (ptr = old_module->module_interface->file_interface; ptr; ptr = ptr->next) {
+			if (ptr->interface_name) {
+				int i;
+				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) {
+						switch_event_add_header(event, SWITCH_STACK_BOTTOM, "type", "file");
+						switch_event_add_header(event, SWITCH_STACK_BOTTOM, "name", "%s", ptr->extens[i]);
+						switch_event_fire(&event);
+					}
+					switch_core_hash_delete(loadable_modules.file_hash, ptr->extens[i]);
+				}
+			}
+		}
+	}
+
+	if (old_module->module_interface->speech_interface) {
+		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_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(event, SWITCH_STACK_BOTTOM, "type", "speech");
+					switch_event_add_header(event, SWITCH_STACK_BOTTOM, "name", "%s", ptr->interface_name);
+					switch_event_fire(&event);
+				}
+				switch_core_hash_delete(loadable_modules.speech_hash, ptr->interface_name);
+			}
+		}
+	}
+
+	if (old_module->module_interface->asr_interface) {
+		const switch_asr_interface_t *ptr;
+
+		for (ptr = old_module->module_interface->asr_interface; ptr; ptr = ptr->next) {
+			if (ptr->interface_name) {
+				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(event, SWITCH_STACK_BOTTOM, "type", "asr");
+					switch_event_add_header(event, SWITCH_STACK_BOTTOM, "name", "%s", ptr->interface_name);
+					switch_event_fire(&event);
+				}
+				switch_core_hash_delete(loadable_modules.asr_hash, ptr->interface_name);
+			}
+		}
+	}
+
+	if (old_module->module_interface->directory_interface) {
+		const switch_directory_interface_t *ptr;
+
+		for (ptr = old_module->module_interface->directory_interface; ptr; ptr = ptr->next) {
+			if (ptr->interface_name) {
+				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(event, SWITCH_STACK_BOTTOM, "type", "directory");
+					switch_event_add_header(event, SWITCH_STACK_BOTTOM, "name", "%s", ptr->interface_name);
+					switch_event_fire(&event);
+				}
+				switch_core_hash_delete(loadable_modules.directory_hash, ptr->interface_name);
+			}
+		}
+	}
+
+
+	if (old_module->module_interface->chat_interface) {
+		const switch_chat_interface_t *ptr;
+
+		for (ptr = old_module->module_interface->chat_interface; ptr; ptr = ptr->next) {
+			if (ptr->interface_name) {				
+				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(event, SWITCH_STACK_BOTTOM, "type", "chat");
+					switch_event_add_header(event, SWITCH_STACK_BOTTOM, "name", "%s", ptr->interface_name);
+					switch_event_fire(&event);
+				}
+				switch_core_hash_delete(loadable_modules.chat_hash, ptr->interface_name);
+			}
+		}
+	}
+
+	if (old_module->module_interface->say_interface) {
+		const switch_say_interface_t *ptr;
+
+		for (ptr = old_module->module_interface->say_interface; ptr; ptr = ptr->next) {
+			if (ptr->interface_name) {
+				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(event, SWITCH_STACK_BOTTOM, "type", "say");
+					switch_event_add_header(event, SWITCH_STACK_BOTTOM, "name", "%s", ptr->interface_name);
+					switch_event_fire(&event);
+				}
+				switch_core_hash_delete(loadable_modules.say_hash, ptr->interface_name);
+			}
+		}
+	}
+
+	if (old_module->module_interface->management_interface) {
+		const switch_management_interface_t *ptr;
+
+		for (ptr = old_module->module_interface->management_interface; ptr; ptr = ptr->next) {
+			if (ptr->relative_oid) {
+				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE,
+								  "Deleting Management interface '%s' OID[%s.%s]\n", old_module->key, FREESWITCH_OID_PREFIX, ptr->relative_oid);
+				switch_core_hash_delete(loadable_modules.management_hash, ptr->relative_oid);
+				if (switch_event_create(&event, SWITCH_EVENT_MODULE_UNLOAD) == SWITCH_STATUS_SUCCESS) {
+					switch_event_add_header(event, SWITCH_STACK_BOTTOM, "type", "management");
+					switch_event_add_header(event, SWITCH_STACK_BOTTOM, "name", "%s", ptr->relative_oid);
+					switch_event_fire(&event);
+				}
+			}
+		}
+	}
+	switch_mutex_unlock(loadable_modules.mutex);
 
 	return SWITCH_STATUS_SUCCESS;
 
 }
 
+
 static switch_status_t switch_loadable_module_load_file(char *filename, switch_loadable_module_t **new_module)
 {
 	switch_loadable_module_t *module = NULL;
@@ -398,12 +649,18 @@
 	const char *err = NULL;
 	switch_loadable_module_interface_t *module_interface = NULL;
 	char derr[512] = "";
+	switch_memory_pool_t *pool;
 
 	assert(filename != NULL);
 
 	*new_module = NULL;
 	status = switch_dso_load(&dso, filename, loadable_modules.pool);
 
+	if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "OH OH no pool\n");
+		abort();
+	}
+
 	while (loading) {
 		if (status != APR_SUCCESS) {
 			switch_dso_error(dso, derr, sizeof(derr));
@@ -419,26 +676,37 @@
 			break;
 		}
 
-		if (load_func_ptr(&module_interface, filename) != SWITCH_STATUS_SUCCESS) {
+		status = load_func_ptr(&module_interface, filename);
+
+		if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_NOUNLOAD) {
 			err = "Module load routine returned an error";
 			module_interface = NULL;
 			break;
 		}
 
-		if ((module = switch_core_permanent_alloc(sizeof(switch_loadable_module_t))) == 0) {
+		if ((module = switch_core_alloc(pool, sizeof(switch_loadable_module_t))) == 0) {
 			err = "Could not allocate memory\n";
-			break;
+			abort();
 		}
 
+		if (status == SWITCH_STATUS_NOUNLOAD) {
+            module->perm++;
+        }
+		
 		loading = 0;
 	}
+	
 
 	if (err) {
+		if (pool) {
+			switch_core_destroy_memory_pool(&pool);
+		}
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Loading module %s\n**%s**\n", filename, err);
 		return SWITCH_STATUS_GENERR;
 	}
 
-	module->filename = switch_core_permanent_strdup(filename);
+	module->pool = pool;
+	module->filename = switch_core_strdup(module->pool, filename);
 	module->module_interface = module_interface;
 	module->switch_module_load = load_func_ptr;
 
@@ -456,7 +724,7 @@
 
 }
 
-SWITCH_DECLARE(switch_status_t) switch_loadable_module_load_module(char *dir, char *fname, switch_bool_t runtime)
+SWITCH_DECLARE(switch_status_t) switch_loadable_module_load_module(char *dir, char *fname, switch_bool_t runtime, const char **err)
 {
 	switch_size_t len = 0;
 	char *path;
@@ -495,18 +763,82 @@
 		}
 	}
 
+	switch_mutex_lock(loadable_modules.mutex);
 	if (switch_core_hash_find(loadable_modules.module_hash, file)) {
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Module %s Already Loaded!\n", file);
-		return SWITCH_STATUS_FALSE;
-	}
-
-	if ((status = switch_loadable_module_load_file(path, &new_module) == SWITCH_STATUS_SUCCESS)) {
+		*err = "Module already loadedn\n";
+		status = SWITCH_STATUS_FALSE;
+	} else if ((status = switch_loadable_module_load_file(path, &new_module) == SWITCH_STATUS_SUCCESS)) {
 		if ((status = switch_loadable_module_process((char *) file, new_module)) == SWITCH_STATUS_SUCCESS && runtime) {
 			if (new_module->switch_module_runtime) {
-				switch_core_launch_thread(switch_loadable_module_exec, new_module, loadable_modules.pool);
+				switch_core_launch_thread(switch_loadable_module_exec, new_module, new_module->pool);
 			}
 		}
 	}
+	switch_mutex_unlock(loadable_modules.mutex);
+
+	return status;
+
+}
+
+
+
+SWITCH_DECLARE(switch_status_t) switch_loadable_module_unload_module(char *dir, char *fname, const char **err)
+{
+	switch_size_t len = 0;
+	char *path = NULL;
+	char *file = NULL;
+	switch_loadable_module_t *module = NULL;
+	switch_status_t status = SWITCH_STATUS_SUCCESS;
+
+#ifdef WIN32
+	const char *ext = ".dll";
+#elif defined (MACOSX) || defined (DARWIN)
+	const char *ext = ".dylib";
+#else
+	const char *ext = ".so";
+#endif
+
+
+	if (!(file = strdup(fname))) {
+		abort();
+	}
+	
+	if (*file == '/') {
+		path = strdup(file);
+	} else {
+		if (strchr(file, '.')) {
+			len = strlen(dir);
+			len += strlen(file);
+			len += 4;
+			path = (char *) switch_core_alloc(loadable_modules.pool, len);
+			snprintf(path, len, "%s%s%s", dir, SWITCH_PATH_SEPARATOR, file);
+		} else {
+			len = strlen(dir);
+			len += strlen(file);
+			len += 8;
+			path = (char *) malloc(len);
+			snprintf(path, len, "%s%s%s%s", dir, SWITCH_PATH_SEPARATOR, file, ext);
+		}
+	}
+
+
+	switch_mutex_lock(loadable_modules.mutex);
+	if ((module = switch_core_hash_find(loadable_modules.module_hash, file))) {
+		if (module->perm) {
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Module is not unloadable.\n");
+			*err = "Module is not unloadable";
+			status = SWITCH_STATUS_NOUNLOAD;
+		} else {
+			do_shutdown(module);
+		}
+	} else {
+		status = SWITCH_STATUS_FALSE;
+	}
+	switch_mutex_unlock(loadable_modules.mutex);
+
+	switch_safe_free(file);
+	switch_safe_free(path);
 
 	return status;
 
@@ -522,40 +854,58 @@
 	int loading = 1;
 	const char *err = NULL;
 	switch_loadable_module_interface_t *module_interface = NULL;
+	switch_memory_pool_t *pool;
 
-	if ((module = switch_core_permanent_alloc(sizeof(switch_loadable_module_t))) == 0) {
+	
+	if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "OH OH no pool\n");
+		abort();
+	}
+
+	if ((module = switch_core_alloc(pool, sizeof(switch_loadable_module_t))) == 0) {
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Couldn't allocate memory\n");
-		return SWITCH_STATUS_GENERR;
+		abort();
 	}
 
+
+
 	while (loading) {
 		load_func_ptr = (switch_module_load_t) switch_module_load;
+		switch_status_t status;
 
 		if (load_func_ptr == NULL) {
 			err = "Cannot Load";
 			break;
 		}
 
-		if (load_func_ptr(&module_interface, filename) != SWITCH_STATUS_SUCCESS) {
+		status = load_func_ptr(&module_interface, filename);
+
+		if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_NOUNLOAD) {
 			err = "Module load routine returned an error";
 			module_interface = NULL;
 			break;
 		}
 
-		if ((module = switch_core_permanent_alloc(sizeof(switch_loadable_module_t))) == 0) {
+		if ((module = switch_core_alloc(pool, sizeof(switch_loadable_module_t))) == 0) {
 			err = "Could not allocate memory\n";
-			break;
+			abort();
+		}
+
+		if (status == SWITCH_STATUS_NOUNLOAD) {
+			module->perm++;
 		}
 
 		loading = 0;
 	}
 
 	if (err) {
+		switch_core_destroy_memory_pool(&pool);
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Error Loading module %s\n**%s**\n", filename, err);
 		return SWITCH_STATUS_GENERR;
 	}
 
-	module->filename = switch_core_permanent_strdup(filename);
+	module->pool = pool;
+	module->filename = switch_core_strdup(module->pool, filename);
 	module->module_interface = module_interface;
 	module->switch_module_load = load_func_ptr;
 
@@ -566,7 +916,7 @@
 		module->switch_module_runtime = switch_module_runtime;
 	}
 	if (module->switch_module_runtime) {
-		switch_core_launch_thread(switch_loadable_module_exec, module, loadable_modules.pool);
+		switch_core_launch_thread(switch_loadable_module_exec, module, module->pool);
 	}
 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Successfully Loaded [%s]\n", module_interface->module_name);
 	return switch_loadable_module_process((char *) module->filename, module);
@@ -599,6 +949,8 @@
 	switch_xml_t cfg, xml;
 	unsigned char all = 0;
 	unsigned int count = 0;
+	const char *err;
+
 
 #ifdef WIN32
 	const char *ext = ".dll";
@@ -633,10 +985,10 @@
 	switch_core_hash_init(&loadable_modules.say_hash, loadable_modules.pool);
 	switch_core_hash_init(&loadable_modules.management_hash, loadable_modules.pool);
 	switch_core_hash_init(&loadable_modules.dialplan_hash, loadable_modules.pool);
+	switch_mutex_init(&loadable_modules.mutex, SWITCH_MUTEX_NESTED, loadable_modules.pool);
 
 	if ((xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
 		switch_xml_t mods, ld;
-
 		if ((mods = switch_xml_child(cfg, "modules"))) {
 			for (ld = switch_xml_child(mods, "load"); ld; ld = ld->next) {
 				const char *val = switch_xml_attr_soft(ld, "module");
@@ -644,7 +996,7 @@
 					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Invalid extension for %s\n", val);
 					continue;
 				}
-				switch_loadable_module_load_module((char *) SWITCH_GLOBAL_dirs.mod_dir, (char *) val, SWITCH_FALSE);
+				switch_loadable_module_load_module((char *) SWITCH_GLOBAL_dirs.mod_dir, (char *) val, SWITCH_FALSE, &err);
 				count++;
 			}
 		}
@@ -664,7 +1016,7 @@
 					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Invalid extension for %s\n", val);
 					continue;
 				}
-				switch_loadable_module_load_module((char *) SWITCH_GLOBAL_dirs.mod_dir, (char *) val, SWITCH_FALSE);
+				switch_loadable_module_load_module((char *) SWITCH_GLOBAL_dirs.mod_dir, (char *) val, SWITCH_FALSE, &err);
 				count++;
 			}
 		}
@@ -687,6 +1039,7 @@
 
 		while (apr_dir_read(&finfo, finfo_flags, module_dir_handle) == APR_SUCCESS) {
 			const char *fname = finfo.fname;
+			const char *err;
 
 			if (finfo.filetype != APR_REG) {
 				continue;
@@ -704,7 +1057,7 @@
 				continue;
 			}
 
-			switch_loadable_module_load_module((char *) SWITCH_GLOBAL_dirs.mod_dir, (char *) fname, SWITCH_FALSE);
+			switch_loadable_module_load_module((char *) SWITCH_GLOBAL_dirs.mod_dir, (char *) fname, SWITCH_FALSE, &err);
 		}
 		apr_dir_close(module_dir_handle);
 	}
@@ -714,35 +1067,58 @@
 	return SWITCH_STATUS_SUCCESS;
 }
 
+static void do_shutdown(switch_loadable_module_t *module)
+{
+	assert(module != NULL);
+
+	switch_loadable_module_unprocess(module);
+
+	if (module->switch_module_shutdown) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Stopping: %s\n", module->module_interface->module_name);
+		if (module->switch_module_shutdown() == SWITCH_STATUS_UNLOAD) {
+			switch_memory_pool_t *pool;
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "%s unloaded.\n", module->module_interface->module_name);
+			switch_dso_unload(module->lib);
+			module->lib = NULL;
+			if ((pool = module->pool)) {
+				module = NULL;
+				switch_core_destroy_memory_pool(&pool);
+			}
+		} else {
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "%s shutdown.\n", module->module_interface->module_name);
+		}
+	} else {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "%s has no shutdown routine\n", module->module_interface->module_name);
+	}
+
+	
+    switch_core_hash_delete_locked(loadable_modules.module_hash, module->key, loadable_modules.mutex);
+		
+}
+
 SWITCH_DECLARE(void) switch_loadable_module_shutdown(void)
 {
 	switch_hash_index_t *hi;
 	void *val;
 	switch_loadable_module_t *module;
-
+	
 	for (hi = switch_hash_first(loadable_modules.pool, loadable_modules.module_hash); hi; hi = switch_hash_next(hi)) {
 		switch_hash_this(hi, NULL, NULL, &val);
 		module = (switch_loadable_module_t *) val;
-
-		if (module->switch_module_shutdown) {
-			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Stopping: %s\n", module->module_interface->module_name);
-			if (module->switch_module_shutdown() == SWITCH_STATUS_UNLOAD) {
-				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "%s unloaded.\n", module->module_interface->module_name);
-				switch_dso_unload(module->lib);
-				module->lib = NULL;
-			} else {
-				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "%s shutdown.\n", module->module_interface->module_name);
-			}
-		} else {
-			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "%s has no shutdown routine\n", module->module_interface->module_name);
-		}
+		do_shutdown(module);
 	}
 
 }
 
 SWITCH_DECLARE(switch_endpoint_interface_t *) switch_loadable_module_get_endpoint_interface(char *name)
 {
-	return switch_core_hash_find(loadable_modules.endpoint_hash, name);
+	switch_endpoint_interface_t *ptr;
+
+	switch_mutex_lock(loadable_modules.mutex);
+	ptr = switch_core_hash_find(loadable_modules.endpoint_hash, name);
+	switch_mutex_unlock(loadable_modules.mutex);
+
+	return ptr;
 }
 
 SWITCH_DECLARE(switch_codec_interface_t *) switch_loadable_module_get_codec_interface(char *name)
@@ -751,6 +1127,7 @@
 	switch_codec_interface_t *codec;
 	switch_size_t x;
 
+	switch_mutex_lock(loadable_modules.mutex);
 	if (!(codec = switch_core_hash_find(loadable_modules.codec_hash, name))) {
 		for (x = 0; x < strlen(name); x++) {
 			altname[x] = (char) toupper((int) name[x]);
@@ -762,62 +1139,63 @@
 			codec = switch_core_hash_find(loadable_modules.codec_hash, altname);
 		}
 	}
+	switch_mutex_unlock(loadable_modules.mutex);
 	return codec;
 }
 
 SWITCH_DECLARE(switch_dialplan_interface_t *) switch_loadable_module_get_dialplan_interface(char *name)
 {
-	return switch_core_hash_find(loadable_modules.dialplan_hash, name);
+	return switch_core_hash_find_locked(loadable_modules.dialplan_hash, name, loadable_modules.mutex);
 }
 
 SWITCH_DECLARE(switch_timer_interface_t *) switch_loadable_module_get_timer_interface(char *name)
 {
-	return switch_core_hash_find(loadable_modules.timer_hash, 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(char *name)
 {
-	return switch_core_hash_find(loadable_modules.application_hash, 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(char *name)
 {
-	return switch_core_hash_find(loadable_modules.api_hash, 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(char *name)
 {
-	return switch_core_hash_find(loadable_modules.file_hash, 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(char *name)
 {
-	return switch_core_hash_find(loadable_modules.speech_hash, 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(char *name)
 {
-	return switch_core_hash_find(loadable_modules.asr_hash, 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(char *name)
 {
-	return switch_core_hash_find(loadable_modules.directory_hash, 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(char *name)
 {
-	return switch_core_hash_find(loadable_modules.chat_hash, name);
+	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(char *name)
 {
-	return switch_core_hash_find(loadable_modules.say_hash, name);
+	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(char *relative_oid)
 {
-	return switch_core_hash_find(loadable_modules.management_hash, relative_oid);
+	return switch_core_hash_find_locked(loadable_modules.management_hash, relative_oid, loadable_modules.mutex);
 }
 
 SWITCH_DECLARE(int) switch_loadable_module_get_codecs(switch_memory_pool_t *pool, const switch_codec_implementation_t **array, int arraylen)
@@ -828,6 +1206,7 @@
 	int i = 0;
 	const switch_codec_implementation_t *imp;
 
+	switch_mutex_lock(loadable_modules.mutex);
 	for (hi = switch_hash_first(pool, loadable_modules.codec_hash); hi; hi = switch_hash_next(hi)) {
 		switch_hash_this(hi, NULL, NULL, &val);
 		codec_interface = (switch_codec_interface_t *) val;
@@ -848,6 +1227,8 @@
 		}
 	}
 
+	switch_mutex_unlock(loadable_modules.mutex);
+	
 	return i;
 
 }
@@ -858,6 +1239,8 @@
 	switch_codec_interface_t *codec_interface;
 	const switch_codec_implementation_t *imp;
 
+	switch_mutex_lock(loadable_modules.mutex);
+	
 	for (x = 0; x < preflen; x++) {
 		char *cur, *last = NULL, *next = NULL, *name, *p, buf[256];
 		uint32_t interval = 0, rate = 0;
@@ -930,6 +1313,9 @@
 		}
 	}
 
+	switch_mutex_unlock(loadable_modules.mutex);
+	
+
 	return i;
 }
 



More information about the Freeswitch-svn mailing list