From 9fe440b2fe63935331b148ffc1d3c7a5ddffa20b Mon Sep 17 00:00:00 2001
From: Andrew Thompson <andrew@hijacked.us>
Date: Fri, 21 Jan 2011 21:53:03 -0500
Subject: [PATCH] mod_erlang_event Add proper locking for the list of XML
 bindings

---
 .../event_handlers/mod_erlang_event/handle_msg.c    |  4 ++--
 .../mod_erlang_event/mod_erlang_event.c             | 13 +++++++++----
 .../mod_erlang_event/mod_erlang_event.h             |  1 +
 3 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/src/mod/event_handlers/mod_erlang_event/handle_msg.c b/src/mod/event_handlers/mod_erlang_event/handle_msg.c
index 9ae15277fd..87f91fc51b 100644
--- a/src/mod/event_handlers/mod_erlang_event/handle_msg.c
+++ b/src/mod/event_handlers/mod_erlang_event/handle_msg.c
@@ -778,7 +778,7 @@ static switch_status_t handle_msg_bind(listener_t *listener, erlang_msg * msg, e
 			binding->process.pid = msg->from;
 			binding->listener = listener;
 
-			switch_thread_rwlock_wrlock(globals.listener_rwlock);
+			switch_thread_rwlock_wrlock(globals.bindings_rwlock);
 
 			for (ptr = bindings.head; ptr && ptr->next; ptr = ptr->next);
 
@@ -789,7 +789,7 @@ static switch_status_t handle_msg_bind(listener_t *listener, erlang_msg * msg, e
 			}
 
 			switch_xml_set_binding_sections(bindings.search_binding, switch_xml_get_binding_sections(bindings.search_binding) | section);
-			switch_thread_rwlock_unlock(globals.listener_rwlock);
+			switch_thread_rwlock_unlock(globals.bindings_rwlock);
 
 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "sections %d\n", switch_xml_get_binding_sections(bindings.search_binding));
 
diff --git a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c
index 1a8bd00790..900b9655ff 100644
--- a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c
+++ b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c
@@ -90,7 +90,7 @@ static void remove_binding(listener_t *listener, erlang_pid * pid)
 {
 	struct erlang_binding *ptr, *lst = NULL;
 
-	switch_thread_rwlock_wrlock(globals.listener_rwlock);
+	switch_thread_rwlock_wrlock(globals.bindings_rwlock);
 
 	switch_xml_set_binding_sections(bindings.search_binding, SWITCH_XML_SECTION_MAX);
 
@@ -100,7 +100,7 @@ static void remove_binding(listener_t *listener, erlang_pid * pid)
 				if (ptr->next) {
 					bindings.head = ptr->next;
 				} else {
-					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Removed all (only?) listeners\n");
+					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Removed all (only?) binding\n");
 					bindings.head = NULL;
 					break;
 				}
@@ -111,13 +111,13 @@ static void remove_binding(listener_t *listener, erlang_pid * pid)
 					lst->next = NULL;
 				}
 			}
-			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Removed listener\n");
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Removed binding\n");
 		} else {
 			switch_xml_set_binding_sections(bindings.search_binding, switch_xml_get_binding_sections(bindings.search_binding) | ptr->section);
 		}
 	}
 
-	switch_thread_rwlock_unlock(globals.listener_rwlock);
+	switch_thread_rwlock_unlock(globals.bindings_rwlock);
 }
 
 
@@ -381,6 +381,8 @@ static switch_xml_t erlang_fetch(const char *sectionstr, const char *tag_name, c
 
 	section = switch_xml_parse_section_string((char *) sectionstr);
 
+	switch_thread_rwlock_rdlock(globals.bindings_rwlock);
+
 	for (ptr = bindings.head; ptr; ptr = ptr->next) {
 		if (ptr->section != section)
 			continue;
@@ -417,6 +419,8 @@ static switch_xml_t erlang_fetch(const char *sectionstr, const char *tag_name, c
 		switch_mutex_unlock(ptr->listener->sock_mutex);
 	}
 
+	switch_thread_rwlock_unlock(globals.bindings_rwlock);
+
 	ei_x_free(&buf);
 
 	if (!p) {
@@ -1638,6 +1642,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_erlang_event_load)
 	memset(&prefs, 0, sizeof(prefs));
 
 	switch_thread_rwlock_create(&globals.listener_rwlock, pool);
+	switch_thread_rwlock_create(&globals.bindings_rwlock, pool);
 	switch_mutex_init(&globals.fetch_reply_mutex, SWITCH_MUTEX_DEFAULT, pool);
 	switch_mutex_init(&globals.listener_count_mutex, SWITCH_MUTEX_UNNESTED, pool);
 	switch_core_hash_init(&globals.fetch_reply_hash, pool);
diff --git a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.h b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.h
index dacfbd661b..121e7b4f95 100644
--- a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.h
+++ b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.h
@@ -161,6 +161,7 @@ struct api_command_struct {
 
 struct globals_struct {
 	switch_thread_rwlock_t *listener_rwlock;
+	switch_thread_rwlock_t *bindings_rwlock;
 	switch_event_node_t *node;
 	switch_mutex_t *ref_mutex;
 	switch_mutex_t *fetch_reply_mutex;