From 1265950eaf5f83b371078f69ed49133ca9bd6ecf Mon Sep 17 00:00:00 2001 From: Exeldro Date: Mon, 20 Nov 2023 07:47:46 +0100 Subject: [PATCH] libobs: Don't keep filter mutex in obs_save_source While filters are saved using obs_save_source other mutex are used. To prevent a deadlock, don't keep the filter mutex iterating the filters. This fixes #9893 --- libobs/obs.c | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/libobs/obs.c b/libobs/obs.c index 949401e09..7f301a712 100644 --- a/libobs/obs.c +++ b/libobs/obs.c @@ -2523,6 +2523,7 @@ obs_data_t *obs_save_source(obs_source_t *source) int m_type = (int)obs_source_get_monitoring_type(source); int di_mode = (int)obs_source_get_deinterlace_mode(source); int di_order = (int)obs_source_get_deinterlace_field_order(source); + DARRAY(obs_source_t *) filters_copy; obs_source_save(source); hotkeys = obs_hotkeys_save_source(source); @@ -2563,20 +2564,31 @@ obs_data_t *obs_save_source(obs_source_t *source) obs_transition_save(source, source_data); pthread_mutex_lock(&source->filter_mutex); + da_init(filters_copy); + da_reserve(filters_copy, source->filters.num); - if (source->filters.num) { - for (size_t i = source->filters.num; i > 0; i--) { - obs_source_t *filter = source->filters.array[i - 1]; - obs_data_t *filter_data = obs_save_source(filter); - obs_data_array_push_back(filters, filter_data); - obs_data_release(filter_data); - } - - obs_data_set_array(source_data, "filters", filters); + for (size_t i = 0; i < source->filters.num; i++) { + obs_source_t *filter = + obs_source_get_ref(source->filters.array[i]); + if (filter) + da_push_back(filters_copy, &filter); } pthread_mutex_unlock(&source->filter_mutex); + if (filters_copy.num) { + for (size_t i = filters_copy.num; i > 0; i--) { + obs_source_t *filter = filters_copy.array[i - 1]; + obs_data_t *filter_data = obs_save_source(filter); + obs_data_array_push_back(filters, filter_data); + obs_data_release(filter_data); + obs_source_release(filter); + } + + obs_data_set_array(source_data, "filters", filters); + da_free(filters_copy); + } + obs_data_release(settings); obs_data_array_release(filters);