mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	context: return -ENOENT for destroyed globals
Set the destroyed flag on globals and make sure they are not available anymore during the signal emissions. One such instance is where a global is destroyed, the resources are destroyed, a waiting client is resumed, the clients asks to bind to the global and causes an error. See #298
This commit is contained in:
		
							parent
							
								
									908dc6b10f
								
							
						
					
					
						commit
						7434986452
					
				
					 4 changed files with 12 additions and 10 deletions
				
			
		| 
						 | 
					@ -496,7 +496,7 @@ struct pw_global *pw_context_find_global(struct pw_context *context, uint32_t id
 | 
				
			||||||
	struct pw_global *global;
 | 
						struct pw_global *global;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	global = pw_map_lookup(&context->globals, id);
 | 
						global = pw_map_lookup(&context->globals, id);
 | 
				
			||||||
	if (global == NULL) {
 | 
						if (global == NULL || global->destroyed) {
 | 
				
			||||||
		errno = ENOENT;
 | 
							errno = ENOENT;
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -37,7 +37,6 @@
 | 
				
			||||||
/** \cond */
 | 
					/** \cond */
 | 
				
			||||||
struct impl {
 | 
					struct impl {
 | 
				
			||||||
	struct pw_global this;
 | 
						struct pw_global this;
 | 
				
			||||||
	bool registered;
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** \endcond */
 | 
					/** \endcond */
 | 
				
			||||||
| 
						 | 
					@ -127,15 +126,14 @@ error_cleanup:
 | 
				
			||||||
SPA_EXPORT
 | 
					SPA_EXPORT
 | 
				
			||||||
int pw_global_register(struct pw_global *global)
 | 
					int pw_global_register(struct pw_global *global)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct impl *impl = SPA_CONTAINER_OF(global, struct impl, this);
 | 
					 | 
				
			||||||
	struct pw_resource *registry;
 | 
						struct pw_resource *registry;
 | 
				
			||||||
	struct pw_context *context = global->context;
 | 
						struct pw_context *context = global->context;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (impl->registered)
 | 
						if (global->registered)
 | 
				
			||||||
		return -EEXIST;
 | 
							return -EEXIST;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_list_append(&context->global_list, &global->link);
 | 
						spa_list_append(&context->global_list, &global->link);
 | 
				
			||||||
	impl->registered = true;
 | 
						global->registered = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_list_for_each(registry, &context->registry_resource_list, link) {
 | 
						spa_list_for_each(registry, &context->registry_resource_list, link) {
 | 
				
			||||||
		uint32_t permissions = pw_global_get_permissions(global, registry->client);
 | 
							uint32_t permissions = pw_global_get_permissions(global, registry->client);
 | 
				
			||||||
| 
						 | 
					@ -157,11 +155,10 @@ int pw_global_register(struct pw_global *global)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int global_unregister(struct pw_global *global)
 | 
					static int global_unregister(struct pw_global *global)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct impl *impl = SPA_CONTAINER_OF(global, struct impl, this);
 | 
					 | 
				
			||||||
	struct pw_context *context = global->context;
 | 
						struct pw_context *context = global->context;
 | 
				
			||||||
	struct pw_resource *resource;
 | 
						struct pw_resource *resource;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!impl->registered)
 | 
						if (!global->registered)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_list_for_each(resource, &context->registry_resource_list, link) {
 | 
						spa_list_for_each(resource, &context->registry_resource_list, link) {
 | 
				
			||||||
| 
						 | 
					@ -173,7 +170,7 @@ static int global_unregister(struct pw_global *global)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_list_remove(&global->link);
 | 
						spa_list_remove(&global->link);
 | 
				
			||||||
	pw_map_remove(&context->globals, global->id);
 | 
						pw_map_remove(&context->globals, global->id);
 | 
				
			||||||
	impl->registered = false;
 | 
						global->registered = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: unregistered %u", global, global->id);
 | 
						pw_log_debug(NAME" %p: unregistered %u", global, global->id);
 | 
				
			||||||
	pw_context_emit_global_removed(context, global);
 | 
						pw_context_emit_global_removed(context, global);
 | 
				
			||||||
| 
						 | 
					@ -215,8 +212,7 @@ SPA_EXPORT
 | 
				
			||||||
int pw_global_update_keys(struct pw_global *global,
 | 
					int pw_global_update_keys(struct pw_global *global,
 | 
				
			||||||
		     const struct spa_dict *dict, const char *keys[])
 | 
							     const struct spa_dict *dict, const char *keys[])
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct impl *impl = SPA_CONTAINER_OF(global, struct impl, this);
 | 
						if (global->registered)
 | 
				
			||||||
	if (impl->registered)
 | 
					 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
	return pw_properties_update_keys(global->properties, dict, keys);
 | 
						return pw_properties_update_keys(global->properties, dict, keys);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -378,6 +374,8 @@ void pw_global_destroy(struct pw_global *global)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct pw_resource *resource;
 | 
						struct pw_resource *resource;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						global->destroyed = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: destroy %u", global, global->id);
 | 
						pw_log_debug(NAME" %p: destroy %u", global, global->id);
 | 
				
			||||||
	pw_global_emit_destroy(global);
 | 
						pw_global_emit_destroy(global);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -700,6 +700,7 @@ void pw_impl_client_set_busy(struct pw_impl_client *client, bool busy)
 | 
				
			||||||
		pw_impl_client_emit_busy_changed(client, busy);
 | 
							pw_impl_client_emit_busy_changed(client, busy);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SPA_EXPORT
 | 
					SPA_EXPORT
 | 
				
			||||||
int pw_impl_client_check_permissions(struct pw_impl_client *client,
 | 
					int pw_impl_client_check_permissions(struct pw_impl_client *client,
 | 
				
			||||||
		uint32_t global_id, uint32_t permissions)
 | 
							uint32_t global_id, uint32_t permissions)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -219,6 +219,9 @@ struct pw_global {
 | 
				
			||||||
	void *object;			/**< object associated with the interface */
 | 
						void *object;			/**< object associated with the interface */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct spa_list resource_list;	/**< The list of resources of this global */
 | 
						struct spa_list resource_list;	/**< The list of resources of this global */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						unsigned int registered:1;
 | 
				
			||||||
 | 
						unsigned int destroyed:1;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define pw_core_resource(r,m,v,...)	pw_resource_call(r, struct pw_core_events, m, v, ##__VA_ARGS__)
 | 
					#define pw_core_resource(r,m,v,...)	pw_resource_call(r, struct pw_core_events, m, v, ##__VA_ARGS__)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue