From 014da683064b93dda81ee4ea3741c570936b8a57 Mon Sep 17 00:00:00 2001 From: Jaco Kroon Date: Thu, 19 Dec 2024 16:45:15 +0200 Subject: [PATCH] res_musiconhold: Appropriately lock channel during start. This relates to #829 This doesn't sully solve the Ops issue, but it solves the specific crash there. Further PRs to follow. In the specific crash the generator was still under construction when moh was being stopped, which then proceeded to close the stream whilst it was still in use. Signed-off-by: Jaco Kroon --- res/res_musiconhold.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/res/res_musiconhold.c b/res/res_musiconhold.c index 02bd7ff1ce..4378324687 100644 --- a/res/res_musiconhold.c +++ b/res/res_musiconhold.c @@ -1687,7 +1687,7 @@ static struct ast_variable *load_realtime_musiconhold(const char *name) static int local_ast_moh_start(struct ast_channel *chan, const char *mclass, const char *interpclass) { struct mohclass *mohclass = NULL; - struct moh_files_state *state = ast_channel_music_state(chan); + struct moh_files_state *state; struct ast_variable *var = NULL; int res = 0; int i; @@ -1762,10 +1762,13 @@ static int local_ast_moh_start(struct ast_channel *chan, const char *mclass, con if (ast_test_flag(global_flags, MOH_CACHERTCLASSES)) { /* CACHERTCLASSES enabled, let's add this class to default tree */ + ast_channel_lock(chan); + state = ast_channel_music_state(chan); if (state && state->class) { /* Class already exist for this channel */ ast_log(LOG_NOTICE, "This channel already has a MOH class attached (%s)!\n", state->class->name); } + ast_channel_unlock(chan); /* We don't want moh_register to unref the mohclass because we do it at the end of this function as well. * If we allowed moh_register to unref the mohclass,too, then the count would be off by one. The result would * be that the destructor would be called when the generator on the channel is deactivated. The container then @@ -1836,6 +1839,8 @@ static int local_ast_moh_start(struct ast_channel *chan, const char *mclass, con } /* Let's check if this channel already had a moh class before */ + ast_channel_lock(chan); + state = ast_channel_music_state(chan); if (state && state->class) { /* Class already exist for this channel */ ast_log(LOG_NOTICE, "This channel already has a MOH class attached (%s)!\n", state->class->name); @@ -1844,7 +1849,9 @@ static int local_ast_moh_start(struct ast_channel *chan, const char *mclass, con mohclass = mohclass_unref(mohclass, "unreffing potential mohclass (channel already has one)"); mohclass = mohclass_ref(state->class, "using existing class from state"); } + ast_channel_unlock(chan); } else { + ast_channel_unlock(chan); if (ast_pthread_create_background(&mohclass->thread, NULL, monmp3thread, mohclass)) { ast_log(LOG_WARNING, "Unable to create moh...\n"); if (mohclass->timer) { @@ -1891,6 +1898,8 @@ static int local_ast_moh_start(struct ast_channel *chan, const char *mclass, con } } + ast_channel_lock(chan); + state = ast_channel_music_state(chan); if (!state || !state->class || strcmp(mohclass->name, state->class->name)) { size_t file_count; @@ -1904,6 +1913,7 @@ static int local_ast_moh_start(struct ast_channel *chan, const char *mclass, con res = ast_activate_generator(chan, &mohgen, mohclass); } } + ast_channel_unlock(chan); if (!res) { ast_channel_lock(chan); ast_channel_latest_musicclass_set(chan, mohclass->name);