浏览代码

libobs: Do not release while traversing sources for tick

obs_source_release should not be called while iterating through the
global sources linked list, otherwise the linked list will be
compromised. Annoying.

Basically the same fix as obsproject/obs-studio#5600, but should be
slightly more optimal and a bit more explicit.
jp9000 3 年之前
父节点
当前提交
080090c40e
共有 3 个文件被更改,包括 16 次插入5 次删除
  1. 2 0
      libobs/obs-internal.h
  2. 13 5
      libobs/obs-video.c
  3. 1 0
      libobs/obs.c

+ 2 - 0
libobs/obs-internal.h

@@ -360,6 +360,8 @@ struct obs_core_data {
 	DARRAY(struct draw_callback) draw_callbacks;
 	DARRAY(struct draw_callback) draw_callbacks;
 	DARRAY(struct tick_callback) tick_callbacks;
 	DARRAY(struct tick_callback) tick_callbacks;
 
 
+	DARRAY(struct obs_source *) source_iteration_list;
+
 	struct obs_view main_view;
 	struct obs_view main_view;
 
 
 	long long unnamed_index;
 	long long unnamed_index;

+ 13 - 5
libobs/obs-video.c

@@ -59,23 +59,31 @@ static uint64_t tick_sources(uint64_t cur_time, uint64_t last_time)
 	/* ------------------------------------- */
 	/* ------------------------------------- */
 	/* call the tick function of each source */
 	/* call the tick function of each source */
 
 
+	da_resize(data->source_iteration_list, 0);
+
 	pthread_mutex_lock(&data->sources_mutex);
 	pthread_mutex_lock(&data->sources_mutex);
 
 
 	source = data->first_source;
 	source = data->first_source;
 	while (source) {
 	while (source) {
 		struct obs_source *cur_source = obs_source_get_ref(source);
 		struct obs_source *cur_source = obs_source_get_ref(source);
-
 		if (cur_source)
 		if (cur_source)
-			obs_source_video_tick(cur_source, seconds);
+			da_push_back(data->source_iteration_list, &cur_source);
 
 
 		source = (struct obs_source *)source->context.next;
 		source = (struct obs_source *)source->context.next;
-
-		if (cur_source)
-			obs_source_release(cur_source);
 	}
 	}
 
 
 	pthread_mutex_unlock(&data->sources_mutex);
 	pthread_mutex_unlock(&data->sources_mutex);
 
 
+	/* obs_source_release should not be called while iterating through
+	 * the global sources linked list, otherwise the linked list will
+	 * be compromised */
+	for (size_t i = 0; i < data->source_iteration_list.num; i++) {
+		struct obs_source *source =
+			data->source_iteration_list.array[i];
+		obs_source_video_tick(source, seconds);
+		obs_source_release(source);
+	}
+
 	return cur_time;
 	return cur_time;
 }
 }
 
 

+ 1 - 0
libobs/obs.c

@@ -696,6 +696,7 @@ static void obs_free_data(void)
 	pthread_mutex_destroy(&data->draw_callbacks_mutex);
 	pthread_mutex_destroy(&data->draw_callbacks_mutex);
 	da_free(data->draw_callbacks);
 	da_free(data->draw_callbacks);
 	da_free(data->tick_callbacks);
 	da_free(data->tick_callbacks);
+	da_free(data->source_iteration_list);
 	obs_data_release(data->private_data);
 	obs_data_release(data->private_data);
 }
 }