]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
res_musiconhold: Appropriately lock channel during start.
authorJaco Kroon <jaco@uls.co.za>
Thu, 19 Dec 2024 14:45:15 +0000 (16:45 +0200)
committergithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Fri, 27 Jun 2025 14:01:24 +0000 (14:01 +0000)
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 <jaco@uls.co.za>
res/res_musiconhold.c

index 02bd7ff1ce57957df99c9d034c49284d862b5d3e..4378324687fedee4068baaf9024a78487200078d 100644 (file)
@@ -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);