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:
Wim Taymans 2020-11-19 11:34:44 +01:00
parent 908dc6b10f
commit 7434986452
4 changed files with 12 additions and 10 deletions

View file

@ -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;
} }

View file

@ -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);

View file

@ -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)

View file

@ -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__)