From 0b9e5c82a5a4a470f3748d8bf1d9a7f5675c80f6 Mon Sep 17 00:00:00 2001 From: Chris Rienzo Date: Mon, 24 Mar 2014 17:03:33 -0400 Subject: [PATCH] FS-6402 mod_rayo/mod_ssml: add mutex to hashes now that iteration is no longer thread-safe --- src/mod/event_handlers/mod_rayo/mod_rayo.c | 15 +++++++++---- .../mod_rayo/rayo_cpa_detector.c | 17 +++++++++----- src/mod/formats/mod_ssml/mod_ssml.c | 22 +++++++++++++++---- 3 files changed, 41 insertions(+), 13 deletions(-) diff --git a/src/mod/event_handlers/mod_rayo/mod_rayo.c b/src/mod/event_handlers/mod_rayo/mod_rayo.c index a793b8ecd4..f9ebc21e9d 100644 --- a/src/mod/event_handlers/mod_rayo/mod_rayo.c +++ b/src/mod/event_handlers/mod_rayo/mod_rayo.c @@ -207,6 +207,8 @@ static struct { char *mixer_conf_profile; /** to URI prefixes mapped to gateways */ switch_hash_t *dial_gateways; + /** synchronizes access to dial gateways */ + switch_mutex_t *dial_gateways_mutex; /** console command aliases */ switch_hash_t *cmd_aliases; /** global console */ @@ -527,7 +529,7 @@ static void broadcast_event(struct rayo_actor *from, iks *rayo_event, int online { switch_hash_index_t *hi = NULL; switch_mutex_lock(globals.clients_mutex); - for (hi = switch_core_hash_first( globals.clients_roster); hi; hi = switch_core_hash_next(hi)) { + for (hi = switch_core_hash_first(globals.clients_roster); hi; hi = switch_core_hash_next(hi)) { struct rayo_client *rclient; const void *key; void *val; @@ -569,6 +571,7 @@ static struct dial_gateway *dial_gateway_find(const char *uri) struct dial_gateway *gateway = (struct dial_gateway *)switch_core_hash_find(globals.dial_gateways, "default"); /* find longest prefix match */ + switch_mutex_lock(globals.dial_gateways_mutex); for (hi = switch_core_hash_first(globals.dial_gateways); hi; hi = switch_core_hash_next(hi)) { struct dial_gateway *candidate = NULL; const void *prefix; @@ -584,6 +587,7 @@ static struct dial_gateway *dial_gateway_find(const char *uri) gateway = candidate; } } + switch_mutex_unlock(globals.dial_gateways_mutex); return gateway; } @@ -1107,7 +1111,7 @@ static void rayo_call_cleanup(struct rayo_actor *actor) } /* send to all offered clients */ - for (hi = switch_core_hash_first( call->pcps); hi; hi = switch_core_hash_next(hi)) { + for (hi = switch_core_hash_first(call->pcps); hi; hi = switch_core_hash_next(hi)) { const void *key; void *val; const char *client_jid = NULL; @@ -2893,6 +2897,7 @@ static void rayo_client_command_recv(struct rayo_client *rclient, iks *iq) static void broadcast_mixer_event(struct rayo_mixer *mixer, iks *rayo_event) { switch_hash_index_t *hi = NULL; + switch_mutex_lock(RAYO_ACTOR(mixer)->mutex); for (hi = switch_core_hash_first(mixer->subscribers); hi; hi = switch_core_hash_next(hi)) { const void *key; void *val; @@ -2903,6 +2908,7 @@ static void broadcast_mixer_event(struct rayo_mixer *mixer, iks *rayo_event) iks_insert_attrib(rayo_event, "to", subscriber->jid); RAYO_SEND_MESSAGE_DUP(mixer, subscriber->jid, rayo_event); } + switch_mutex_unlock(RAYO_ACTOR(mixer)->mutex); } /** @@ -3609,7 +3615,7 @@ SWITCH_STANDARD_APP(rayo_app) /* Offer call to all ONLINE clients */ /* TODO load balance offers so first session doesn't always get offer first? */ switch_mutex_lock(globals.clients_mutex); - for (hi = switch_core_hash_first( globals.clients_roster); hi; hi = switch_core_hash_next(hi)) { + for (hi = switch_core_hash_first(globals.clients_roster); hi; hi = switch_core_hash_next(hi)) { struct rayo_client *rclient; const void *key; void *val; @@ -4364,7 +4370,7 @@ static switch_status_t list_actors(const char *line, const char *cursor, switch_ struct rayo_actor *actor; switch_mutex_lock(globals.actors_mutex); - for (hi = switch_core_hash_first( globals.actors); hi; hi = switch_core_hash_next(hi)) { + for (hi = switch_core_hash_first(globals.actors); hi; hi = switch_core_hash_next(hi)) { switch_core_hash_this(hi, &vvar, NULL, &val); actor = (struct rayo_actor *) val; @@ -4549,6 +4555,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_rayo_load) switch_core_hash_init(&globals.actors_by_id); switch_mutex_init(&globals.actors_mutex, SWITCH_MUTEX_NESTED, pool); switch_core_hash_init(&globals.dial_gateways); + switch_mutex_init(&globals.dial_gateways_mutex, SWITCH_MUTEX_NESTED, pool); switch_core_hash_init(&globals.cmd_aliases); switch_thread_rwlock_create(&globals.shutdown_rwlock, pool); switch_queue_create(&globals.msg_queue, 25000, pool); diff --git a/src/mod/event_handlers/mod_rayo/rayo_cpa_detector.c b/src/mod/event_handlers/mod_rayo/rayo_cpa_detector.c index 1f4cbb58ee..0d8bba26cd 100644 --- a/src/mod/event_handlers/mod_rayo/rayo_cpa_detector.c +++ b/src/mod/event_handlers/mod_rayo/rayo_cpa_detector.c @@ -31,6 +31,8 @@ static struct { /** detectors supported by this module mapped by signal-type */ switch_hash_t *detectors; + /** synchronizes access to detectors */ + switch_mutex_t *detectors_mutex; } globals; struct rayo_cpa_detector; @@ -390,10 +392,12 @@ static switch_status_t rayo_cpa_detector_signal_types(const char *line, const ch const void *vvar; switch_console_callback_match_t *my_matches = NULL; - for (hi = switch_core_hash_first( globals.detectors); hi; hi = switch_core_hash_next(hi)) { + switch_mutex_lock(globals.detectors_mutex); + for (hi = switch_core_hash_first(globals.detectors); hi; hi = switch_core_hash_next(hi)) { switch_core_hash_this(hi, &vvar, NULL, &val); switch_console_push_match(&my_matches, (const char *) vvar); } + switch_mutex_unlock(globals.detectors_mutex); if (my_matches) { *matches = my_matches; @@ -414,16 +418,19 @@ switch_status_t rayo_cpa_detector_load(switch_loadable_module_interface_t **modu { switch_api_interface_t *api_interface; + switch_core_hash_init(&globals.detectors); + switch_mutex_init(&globals.detectors_mutex, SWITCH_MUTEX_NESTED, pool); + + if (do_config(pool, config_file) != SWITCH_STATUS_SUCCESS) { + return SWITCH_STATUS_TERM; + } + SWITCH_ADD_API(api_interface, "rayo_cpa", "Query rayo status", rayo_cpa_detector_api, RAYO_CPA_DETECTOR_SYNTAX); switch_console_set_complete("add rayo_cpa ::console::list_uuid ::rayo_cpa::list_signal_types start"); switch_console_set_complete("add rayo_cpa ::console::list_uuid ::rayo_cpa::list_signal_types stop"); switch_console_add_complete_func("::rayo_cpa::list_signal_types", rayo_cpa_detector_signal_types); - switch_core_hash_init(&globals.detectors); - if (do_config(pool, config_file) != SWITCH_STATUS_SUCCESS) { - return SWITCH_STATUS_TERM; - } return SWITCH_STATUS_SUCCESS; } diff --git a/src/mod/formats/mod_ssml/mod_ssml.c b/src/mod/formats/mod_ssml/mod_ssml.c index eb227cbad4..c989ee1a8e 100644 --- a/src/mod/formats/mod_ssml/mod_ssml.c +++ b/src/mod/formats/mod_ssml/mod_ssml.c @@ -1,6 +1,6 @@ /* * mod_ssml for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application - * Copyright (C) 2013, Grasshopper + * Copyright (C) 2013-2014, Grasshopper * * Version: MPL 1.1 * @@ -64,8 +64,12 @@ static struct { switch_hash_t *voice_cache; /** Mapping of voice names */ switch_hash_t *say_voice_map; + /** Synchronizes access to say_voice_map */ + switch_mutex_t *say_voice_map_mutex; /** Mapping of voice names */ switch_hash_t *tts_voice_map; + /** Synchronizes access to tts_voice_map */ + switch_mutex_t *tts_voice_map_mutex; /** Mapping of interpret-as value to macro */ switch_hash_t *interpret_as_map; /** Mapping of ISO language code to say-module */ @@ -339,7 +343,7 @@ static struct voice *find_voice(struct ssml_node *cur_node, switch_hash_t *map, } /* find best language, name, gender match */ - for (hi = switch_core_hash_first( map); hi; hi = switch_core_hash_next(hi)) { + for (hi = switch_core_hash_first(map); hi; hi = switch_core_hash_next(hi)) { const void *key; void *val; struct voice *candidate; @@ -371,7 +375,11 @@ done: */ static struct voice *find_tts_voice(struct ssml_node *cur_node) { - return find_voice(cur_node, globals.tts_voice_map, "tts", 0); + struct voice *v; + switch_mutex_lock(globals.tts_voice_map_mutex); + v = find_voice(cur_node, globals.tts_voice_map, "tts", 0); + switch_mutex_unlock(globals.tts_voice_map_mutex); + return v; } /** @@ -381,7 +389,11 @@ static struct voice *find_tts_voice(struct ssml_node *cur_node) */ static struct voice *find_say_voice(struct ssml_node *cur_node) { - return find_voice(cur_node, globals.say_voice_map, "say", 1); + struct voice *v; + switch_mutex_lock(globals.say_voice_map_mutex); + v = find_voice(cur_node, globals.say_voice_map, "say", 1); + switch_mutex_unlock(globals.say_voice_map_mutex); + return v; } /** @@ -1112,7 +1124,9 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_ssml_load) globals.pool = pool; switch_core_hash_init(&globals.voice_cache); switch_core_hash_init(&globals.tts_voice_map); + switch_mutex_init(&globals.tts_voice_map_mutex, SWITCH_MUTEX_NESTED, pool); switch_core_hash_init(&globals.say_voice_map); + switch_mutex_init(&globals.say_voice_map_mutex, SWITCH_MUTEX_NESTED, pool); switch_core_hash_init(&globals.interpret_as_map); switch_core_hash_init(&globals.language_map); switch_core_hash_init(&globals.tag_defs);