mirror of
https://github.com/asterisk/asterisk.git
synced 2026-06-09 11:55:19 +00:00
res_stasis/resource_bridges: Split bridge playback control and wrapper cleanup
Modified the bridge playback teardown so the worker thread removes only the playback control, while the after-bridge callback removes the playback wrapper once the announcer has actually left the bridge. This avoids a stale window where a new playback request could create a replacement announcer before the old announcer had fully exited the holding bridge. Also replaced the flexible trailing bridge_id storage in the shared worker thread data with an optional bridge_id pointer, since recording paths use the same structure without a bridge id. Fixes: #1861
This commit is contained in:
committed by
github-actions[bot]
parent
d94025d5df
commit
176ecdad3c
@@ -795,6 +795,15 @@ int stasis_app_bridge_playback_channel_add(struct ast_bridge *bridge,
|
||||
struct ast_channel *chan,
|
||||
struct stasis_app_control *control);
|
||||
|
||||
/*!
|
||||
* \brief Remove a bridge playback channel's control from the app controls list.
|
||||
*
|
||||
* \param bridge_id The unique ID of the bridge the playback channel is in.
|
||||
* \param control The app control structure for the playback channel
|
||||
*/
|
||||
void stasis_app_bridge_playback_channel_control_remove(const char *bridge_id,
|
||||
struct stasis_app_control *control);
|
||||
|
||||
/*!
|
||||
* \brief remove channel from list of ARI playback channels for bridges.
|
||||
*
|
||||
|
||||
@@ -282,7 +282,7 @@ struct bridge_channel_control_thread_data {
|
||||
struct ast_channel *bridge_channel;
|
||||
struct stasis_app_control *control;
|
||||
struct stasis_forward *forward;
|
||||
char bridge_id[0];
|
||||
char *bridge_id;
|
||||
};
|
||||
|
||||
static void *bridge_channel_control_thread(void *data)
|
||||
@@ -292,7 +292,7 @@ static void *bridge_channel_control_thread(void *data)
|
||||
struct stasis_app_control *control = thread_data->control;
|
||||
struct stasis_forward *forward = thread_data->forward;
|
||||
ast_callid callid = ast_channel_callid(bridge_channel);
|
||||
char *bridge_id = ast_strdupa(thread_data->bridge_id);
|
||||
char *bridge_id = thread_data->bridge_id;
|
||||
|
||||
if (callid) {
|
||||
ast_callid_threadassoc_add(callid);
|
||||
@@ -304,7 +304,10 @@ static void *bridge_channel_control_thread(void *data)
|
||||
stasis_app_control_execute_until_exhausted(bridge_channel, control);
|
||||
stasis_app_control_flush_queue(control);
|
||||
|
||||
stasis_app_bridge_playback_channel_remove(bridge_id, control);
|
||||
if (bridge_id) {
|
||||
stasis_app_bridge_playback_channel_control_remove(bridge_id, control);
|
||||
ast_free(bridge_id);
|
||||
}
|
||||
stasis_forward_cancel(forward);
|
||||
ao2_cleanup(control);
|
||||
ast_hangup(bridge_channel);
|
||||
@@ -532,7 +535,7 @@ static void ari_bridges_play_new(const char **args_media,
|
||||
ast_bridge_queue_everyone_else(bridge, NULL, &prog);
|
||||
|
||||
/* Give play_channel and control reference to the thread data */
|
||||
thread_data = ast_malloc(sizeof(*thread_data) + strlen(bridge->uniqueid) + 1);
|
||||
thread_data = ast_calloc(1, sizeof(*thread_data));
|
||||
if (!thread_data) {
|
||||
stasis_app_bridge_playback_channel_remove((char *)bridge->uniqueid, control);
|
||||
ast_ari_response_alloc_failed(response);
|
||||
@@ -542,11 +545,17 @@ static void ari_bridges_play_new(const char **args_media,
|
||||
thread_data->bridge_channel = play_channel;
|
||||
thread_data->control = control;
|
||||
thread_data->forward = channel_forward;
|
||||
/* Safe */
|
||||
strcpy(thread_data->bridge_id, bridge->uniqueid);
|
||||
thread_data->bridge_id = ast_strdup(bridge->uniqueid);
|
||||
if (!thread_data->bridge_id) {
|
||||
stasis_app_bridge_playback_channel_remove((char *)bridge->uniqueid, control);
|
||||
ast_ari_response_alloc_failed(response);
|
||||
ast_free(thread_data);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ast_pthread_create_detached(&threadid, NULL, bridge_channel_control_thread, thread_data)) {
|
||||
stasis_app_bridge_playback_channel_remove((char *)bridge->uniqueid, control);
|
||||
ast_free(thread_data->bridge_id);
|
||||
ast_ari_response_alloc_failed(response);
|
||||
ast_free(thread_data);
|
||||
return;
|
||||
@@ -653,7 +662,7 @@ static void ari_bridges_handle_play(
|
||||
* in which case we'll revert to ari_bridges_play_new.
|
||||
*/
|
||||
if (ari_bridges_play_found(args_media, args_media_count, args_lang,
|
||||
args_offset_ms, args_skipms, args_playback_id, response,bridge,
|
||||
args_offset_ms, args_skipms, args_playback_id, response, bridge,
|
||||
play_channel) == PLAY_FOUND_CHANNEL_UNAVAILABLE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -714,6 +714,13 @@ static void remove_bridge_playback(char *bridge_id)
|
||||
ast_free(bridge_id);
|
||||
}
|
||||
|
||||
void stasis_app_bridge_playback_channel_control_remove(const char *bridge_id,
|
||||
struct stasis_app_control *control)
|
||||
{
|
||||
ast_assert(!ast_strlen_zero(bridge_id));
|
||||
ao2_unlink(app_controls, control);
|
||||
}
|
||||
|
||||
static void playback_after_bridge_cb_failed(enum ast_bridge_after_cb_reason reason, void *data)
|
||||
{
|
||||
char *bridge_id = data;
|
||||
@@ -777,7 +784,7 @@ void stasis_app_bridge_playback_channel_remove(char *bridge_id,
|
||||
* called or is in progress. No need to unlink the control here since that has
|
||||
* been done or is about to be done in the after bridge callback
|
||||
*/
|
||||
ao2_unlink(app_controls, control);
|
||||
stasis_app_bridge_playback_channel_control_remove(bridge_id, control);
|
||||
ao2_ref(wrapper, -1);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user