mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	loop: handle remove while dispatching better
Keep the array of dispatched sources around in the loop. When a source is removed while dispatching, set the data to NULL so that we don't try to deref the source again or call its function. Fixes #2114
This commit is contained in:
		
							parent
							
								
									afc88a12e5
								
							
						
					
					
						commit
						45d911641b
					
				
					 1 changed files with 16 additions and 5 deletions
				
			
		| 
						 | 
					@ -48,6 +48,7 @@ static struct spa_log_topic log_topic = SPA_LOG_TOPIC(0, "spa.loop");
 | 
				
			||||||
#define MAX_ALIGN	8
 | 
					#define MAX_ALIGN	8
 | 
				
			||||||
#define ITEM_ALIGN	8
 | 
					#define ITEM_ALIGN	8
 | 
				
			||||||
#define DATAS_SIZE	(4096*8)
 | 
					#define DATAS_SIZE	(4096*8)
 | 
				
			||||||
 | 
					#define MAX_EP		32
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** \cond */
 | 
					/** \cond */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -80,6 +81,9 @@ struct impl {
 | 
				
			||||||
	int poll_fd;
 | 
						int poll_fd;
 | 
				
			||||||
	pthread_t thread;
 | 
						pthread_t thread;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct spa_poll_event dispatching[MAX_EP];
 | 
				
			||||||
 | 
						uint32_t n_dispatching;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct spa_source *wakeup;
 | 
						struct spa_source *wakeup;
 | 
				
			||||||
	int ack_fd;
 | 
						int ack_fd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -125,6 +129,11 @@ static int loop_update_source(void *object, struct spa_source *source)
 | 
				
			||||||
static int loop_remove_source(void *object, struct spa_source *source)
 | 
					static int loop_remove_source(void *object, struct spa_source *source)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct impl *impl = object;
 | 
						struct impl *impl = object;
 | 
				
			||||||
 | 
						uint32_t i;
 | 
				
			||||||
 | 
						for (i = 0; i < impl->n_dispatching; i++) {
 | 
				
			||||||
 | 
							if (impl->dispatching[i].data == source)
 | 
				
			||||||
 | 
								impl->dispatching[i].data = NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	source->loop = NULL;
 | 
						source->loop = NULL;
 | 
				
			||||||
	return spa_system_pollfd_del(impl->system, impl->poll_fd, source->fd);
 | 
						return spa_system_pollfd_del(impl->system, impl->poll_fd, source->fd);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -311,13 +320,12 @@ static inline void process_destroy(struct impl *impl)
 | 
				
			||||||
static int loop_iterate(void *object, int timeout)
 | 
					static int loop_iterate(void *object, int timeout)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct impl *impl = object;
 | 
						struct impl *impl = object;
 | 
				
			||||||
	struct spa_loop *loop = &impl->loop;
 | 
						struct spa_poll_event *ep = impl->dispatching;
 | 
				
			||||||
	struct spa_poll_event ep[32];
 | 
					 | 
				
			||||||
	int i, nfds;
 | 
						int i, nfds;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_loop_control_hook_before(&impl->hooks_list);
 | 
						spa_loop_control_hook_before(&impl->hooks_list);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	nfds = spa_system_pollfd_wait(impl->system, impl->poll_fd, ep, SPA_N_ELEMENTS(ep), timeout);
 | 
						nfds = spa_system_pollfd_wait(impl->system, impl->poll_fd, ep, MAX_EP, timeout);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_loop_control_hook_after(&impl->hooks_list);
 | 
						spa_loop_control_hook_after(&impl->hooks_list);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -329,16 +337,19 @@ static int loop_iterate(void *object, int timeout)
 | 
				
			||||||
	 * can then reset the rmask to suppress the callback */
 | 
						 * can then reset the rmask to suppress the callback */
 | 
				
			||||||
	for (i = 0; i < nfds; i++) {
 | 
						for (i = 0; i < nfds; i++) {
 | 
				
			||||||
		struct spa_source *s = ep[i].data;
 | 
							struct spa_source *s = ep[i].data;
 | 
				
			||||||
		s->rmask = ep[i].events;
 | 
							if (SPA_LIKELY(s))
 | 
				
			||||||
 | 
								s->rmask = ep[i].events;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						impl->n_dispatching = nfds;
 | 
				
			||||||
	for (i = 0; i < nfds; i++) {
 | 
						for (i = 0; i < nfds; i++) {
 | 
				
			||||||
		struct spa_source *s = ep[i].data;
 | 
							struct spa_source *s = ep[i].data;
 | 
				
			||||||
		if (SPA_LIKELY(s->rmask && s->fd != -1 && s->loop == loop))
 | 
							if (SPA_LIKELY(s && s->rmask))
 | 
				
			||||||
			s->func(s);
 | 
								s->func(s);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (SPA_UNLIKELY(!spa_list_is_empty(&impl->destroy_list)))
 | 
						if (SPA_UNLIKELY(!spa_list_is_empty(&impl->destroy_list)))
 | 
				
			||||||
		process_destroy(impl);
 | 
							process_destroy(impl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						impl->n_dispatching = 0;
 | 
				
			||||||
	return nfds;
 | 
						return nfds;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue