mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	loop: handle file fd with eventfd
epoll return EPERM for file fds like stdin/stdout because they are always ready for IO. use an idle source to handle these cases.
This commit is contained in:
		
							parent
							
								
									30fac2b242
								
							
						
					
					
						commit
						d1beeeade0
					
				
					 1 changed files with 32 additions and 6 deletions
				
			
		| 
						 | 
					@ -97,6 +97,7 @@ struct source_impl {
 | 
				
			||||||
		spa_source_signal_func_t signal;
 | 
							spa_source_signal_func_t signal;
 | 
				
			||||||
	} func;
 | 
						} func;
 | 
				
			||||||
	bool enabled;
 | 
						bool enabled;
 | 
				
			||||||
 | 
						struct spa_source *fallback;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
/** \endcond */
 | 
					/** \endcond */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -309,6 +310,7 @@ static int loop_iterate(void *object, int timeout)
 | 
				
			||||||
static void source_io_func(struct spa_source *source)
 | 
					static void source_io_func(struct spa_source *source)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct source_impl *impl = SPA_CONTAINER_OF(source, struct source_impl, source);
 | 
						struct source_impl *impl = SPA_CONTAINER_OF(source, struct source_impl, source);
 | 
				
			||||||
 | 
						spa_log_trace(impl->impl->log, NAME" %p: io %08x", impl, source->rmask);
 | 
				
			||||||
	impl->func.io(source->data, source->fd, source->rmask);
 | 
						impl->func.io(source->data, source->fd, source->rmask);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -334,9 +336,21 @@ static struct spa_source *loop_add_io(void *object,
 | 
				
			||||||
	source->close = close;
 | 
						source->close = close;
 | 
				
			||||||
	source->func.io = func;
 | 
						source->func.io = func;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((res = loop_add_source(impl, &source->source)) < 0)
 | 
						if ((res = loop_add_source(impl, &source->source)) < 0) {
 | 
				
			||||||
 | 
							if (res != -EPERM)
 | 
				
			||||||
			goto error_exit_free;
 | 
								goto error_exit_free;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* file fds (stdin/stdout/...) give EPERM in epoll. Those fds always
 | 
				
			||||||
 | 
							 * return from epoll with the mask set, so we can handle this with
 | 
				
			||||||
 | 
							 * an idle source */
 | 
				
			||||||
 | 
							source->source.rmask = mask;
 | 
				
			||||||
 | 
							source->fallback = spa_loop_utils_add_idle(&impl->utils,
 | 
				
			||||||
 | 
									mask & (SPA_IO_IN | SPA_IO_OUT) ? true : false,
 | 
				
			||||||
 | 
									(spa_source_idle_func_t) source_io_func, source);
 | 
				
			||||||
 | 
							spa_log_trace(impl->log, NAME" %p: adding fallback %p", impl,
 | 
				
			||||||
 | 
									source->fallback);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_list_insert(&impl->source_list, &source->link);
 | 
						spa_list_insert(&impl->source_list, &source->link);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return &source->source;
 | 
						return &source->source;
 | 
				
			||||||
| 
						 | 
					@ -350,18 +364,25 @@ error_exit:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int loop_update_io(void *object, struct spa_source *source, uint32_t mask)
 | 
					static int loop_update_io(void *object, struct spa_source *source, uint32_t mask)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						struct impl *impl = object;
 | 
				
			||||||
 | 
						struct source_impl *s = SPA_CONTAINER_OF(source, struct source_impl, source);
 | 
				
			||||||
 | 
						int res;
 | 
				
			||||||
	source->mask = mask;
 | 
						source->mask = mask;
 | 
				
			||||||
	return loop_update_source(object, source);
 | 
						spa_log_trace(impl->log, NAME" %p: update %08x", s, mask);
 | 
				
			||||||
 | 
						if (s->fallback)
 | 
				
			||||||
 | 
							res = spa_loop_utils_enable_idle(&impl->utils, s->fallback,
 | 
				
			||||||
 | 
									mask & (SPA_IO_IN | SPA_IO_OUT) ? true : false);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							res = loop_update_source(object, source);
 | 
				
			||||||
 | 
						return res;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
static void source_idle_func(struct spa_source *source)
 | 
					static void source_idle_func(struct spa_source *source)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct source_impl *impl = SPA_CONTAINER_OF(source, struct source_impl, source);
 | 
						struct source_impl *impl = SPA_CONTAINER_OF(source, struct source_impl, source);
 | 
				
			||||||
	impl->func.idle(source->data);
 | 
						impl->func.idle(source->data);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
static int loop_enable_idle(void *object, struct spa_source *source, bool enabled)
 | 
					static int loop_enable_idle(void *object, struct spa_source *source, bool enabled)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct source_impl *impl = SPA_CONTAINER_OF(source, struct source_impl, source);
 | 
						struct source_impl *impl = SPA_CONTAINER_OF(source, struct source_impl, source);
 | 
				
			||||||
| 
						 | 
					@ -380,6 +401,7 @@ static int loop_enable_idle(void *object, struct spa_source *source, bool enable
 | 
				
			||||||
	impl->enabled = enabled;
 | 
						impl->enabled = enabled;
 | 
				
			||||||
	return res;
 | 
						return res;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct spa_source *loop_add_idle(void *object,
 | 
					static struct spa_source *loop_add_idle(void *object,
 | 
				
			||||||
					bool enabled, spa_source_idle_func_t func, void *data)
 | 
										bool enabled, spa_source_idle_func_t func, void *data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -622,9 +644,13 @@ static void loop_destroy_source(void *object, struct spa_source *source)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct source_impl *impl = SPA_CONTAINER_OF(source, struct source_impl, source);
 | 
						struct source_impl *impl = SPA_CONTAINER_OF(source, struct source_impl, source);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spa_log_trace(impl->impl->log, NAME" %p ", impl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_list_remove(&impl->link);
 | 
						spa_list_remove(&impl->link);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (source->loop)
 | 
						if (impl->fallback)
 | 
				
			||||||
 | 
							loop_destroy_source(impl->impl, impl->fallback);
 | 
				
			||||||
 | 
						else if (source->loop)
 | 
				
			||||||
		loop_remove_source(impl->impl, source);
 | 
							loop_remove_source(impl->impl, source);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (source->fd != -1 && impl->close) {
 | 
						if (source->fd != -1 && impl->close) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue