From 1570e626352a949e1c7cc57049da7e9fcbc1d22c Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 6 Nov 2020 15:53:32 +0100 Subject: [PATCH] remove hooks from objects Remove the hooks we installed on objects in the destroy/free event or before calling _destroy. This is not really needed but it is a nice thing to do because it calls the hook removed callbacks. --- pipewire-pulseaudio/src/context.c | 4 +++ src/examples/media-session/media-session.c | 14 +++++++--- src/modules/module-adapter.c | 1 + src/modules/module-adapter/adapter.c | 1 + .../module-client-device/proxy-device.c | 2 ++ src/modules/module-link-factory.c | 1 + src/modules/module-metadata/metadata.c | 2 ++ src/modules/module-metadata/proxy-metadata.c | 2 ++ src/modules/module-protocol-native.c | 16 ++++++++++++ src/modules/module-protocol-pulse/manager.c | 6 ++++- src/modules/spa/module-device-factory.c | 1 + src/pipewire/context.c | 5 ---- src/pipewire/core.c | 3 +++ src/pipewire/impl-client.c | 26 +++++++++++-------- src/pipewire/impl-core.c | 22 +++++++++++----- src/pipewire/impl-device.c | 5 ++++ src/pipewire/impl-node.c | 2 ++ src/pipewire/impl-port.c | 16 ++++++++++++ src/tools/pw-cli.c | 7 +++++ 19 files changed, 109 insertions(+), 27 deletions(-) diff --git a/pipewire-pulseaudio/src/context.c b/pipewire-pulseaudio/src/context.c index 758c78ac1..8bc66dc23 100644 --- a/pipewire-pulseaudio/src/context.c +++ b/pipewire-pulseaudio/src/context.c @@ -79,10 +79,12 @@ static void context_unlink(pa_context *c) PA_STREAM_FAILED : PA_STREAM_TERMINATED); } if (c->registry) { + spa_hook_remove(&c->core_listener), pw_proxy_destroy((struct pw_proxy*)c->registry); c->registry = NULL; } if (c->core) { + spa_hook_remove(&c->core_listener); pw_core_disconnect(c->core); c->core = NULL; } @@ -1897,10 +1899,12 @@ void pa_context_disconnect(pa_context *c) c->disconnect = true; if (c->registry) { + spa_hook_remove(&c->registry_listener), pw_proxy_destroy((struct pw_proxy*)c->registry); c->registry = NULL; } if (c->core) { + spa_hook_remove(&c->core_listener), pw_core_disconnect(c->core); c->core = NULL; } diff --git a/src/examples/media-session/media-session.c b/src/examples/media-session/media-session.c index 44da348de..16105b505 100644 --- a/src/examples/media-session/media-session.c +++ b/src/examples/media-session/media-session.c @@ -1518,6 +1518,7 @@ static void proxy_link_destroy(void *data) struct link *l = data; spa_list_remove(&l->link); + spa_hook_remove(&l->listener); if (l->endpoint_link) { check_endpoint_link(l->endpoint_link); @@ -2032,12 +2033,19 @@ static void session_shutdown(struct impl *impl) sm_media_session_emit_destroy(impl); - if (impl->registry) + if (impl->registry) { + spa_hook_remove(&impl->registry_listener); pw_proxy_destroy((struct pw_proxy*)impl->registry); - if (impl->policy_core) + } + if (impl->policy_core) { + spa_hook_remove(&impl->policy_listener); + spa_hook_remove(&impl->proxy_policy_listener); pw_core_disconnect(impl->policy_core); - if (impl->monitor_core) + } + if (impl->monitor_core) { + spa_hook_remove(&impl->monitor_listener); pw_core_disconnect(impl->monitor_core); + } if (impl->this.info) pw_core_info_free(impl->this.info); } diff --git a/src/modules/module-adapter.c b/src/modules/module-adapter.c index 65d7117de..ed92d10ea 100644 --- a/src/modules/module-adapter.c +++ b/src/modules/module-adapter.c @@ -91,6 +91,7 @@ static void node_destroy(void *data) struct node_data *nd = data; pw_log_debug(NAME" %p: destroy %p", nd, nd->adapter); spa_list_remove(&nd->link); + spa_hook_remove(&nd->adapter_listener); nd->adapter = NULL; } diff --git a/src/modules/module-adapter/adapter.c b/src/modules/module-adapter/adapter.c index 5fe99684f..11b0d56ee 100644 --- a/src/modules/module-adapter/adapter.c +++ b/src/modules/module-adapter/adapter.c @@ -77,6 +77,7 @@ struct node { static void node_free(void *data) { struct node *n = data; + spa_hook_remove(&n->node_listener); pw_properties_free(n->props); } diff --git a/src/modules/module-client-device/proxy-device.c b/src/modules/module-client-device/proxy-device.c index b704f7c7a..6c78d3151 100644 --- a/src/modules/module-client-device/proxy-device.c +++ b/src/modules/module-client-device/proxy-device.c @@ -44,6 +44,8 @@ static void proxy_device_destroy(void *_data) { struct device_data *data = _data; spa_hook_remove(&data->device_listener); + spa_hook_remove(&data->device_methods); + spa_hook_remove(&data->proxy_listener); } static const struct pw_proxy_events proxy_events = { diff --git a/src/modules/module-link-factory.c b/src/modules/module-link-factory.c index 2f1d73ab1..7cb177cd9 100644 --- a/src/modules/module-link-factory.c +++ b/src/modules/module-link-factory.c @@ -104,6 +104,7 @@ static void link_destroy(void *data) { struct link_data *ld = data; spa_list_remove(&ld->l); + spa_hook_remove(&ld->link_listener); if (ld->global) spa_hook_remove(&ld->global_listener); if (ld->resource) diff --git a/src/modules/module-metadata/metadata.c b/src/modules/module-metadata/metadata.c index 6035ba8ba..13461edb6 100644 --- a/src/modules/module-metadata/metadata.c +++ b/src/modules/module-metadata/metadata.c @@ -123,6 +123,8 @@ static void global_unbind(void *data) { struct resource_data *d = data; if (d->resource) { + spa_hook_remove(&d->resource_listener); + spa_hook_remove(&d->object_listener); spa_hook_remove(&d->metadata_listener); spa_hook_remove(&d->impl_resource_listener); } diff --git a/src/modules/module-metadata/proxy-metadata.c b/src/modules/module-metadata/proxy-metadata.c index bf8482fb3..1d8a675ed 100644 --- a/src/modules/module-metadata/proxy-metadata.c +++ b/src/modules/module-metadata/proxy-metadata.c @@ -43,7 +43,9 @@ struct object_data { static void proxy_object_destroy(void *_data) { struct object_data *data = _data; + spa_hook_remove(&data->proxy_listener); spa_hook_remove(&data->object_listener); + spa_hook_remove(&data->object_methods); } static const struct pw_proxy_events proxy_events = { diff --git a/src/modules/module-protocol-native.c b/src/modules/module-protocol-native.c index 965d20585..c02a39a5a 100644 --- a/src/modules/module-protocol-native.c +++ b/src/modules/module-protocol-native.c @@ -315,6 +315,8 @@ static void client_free(void *data) pw_log_debug(NAME" %p: free", this); spa_list_remove(&this->protocol_link); + spa_hook_remove(&this->client_listener); + if (this->source) pw_loop_destroy_source(client->context->main_loop, this->source); if (this->connection) @@ -329,6 +331,12 @@ static const struct pw_impl_client_events client_events = { .busy_changed = client_busy_changed, }; +static void on_server_connection_destroy(void *data) +{ + struct client_data *this = data; + spa_hook_remove(&this->conn_listener); +} + static void on_start(void *data, uint32_t version) { struct client_data *this = data; @@ -351,6 +359,7 @@ static void on_start(void *data, uint32_t version) static const struct pw_protocol_native_connection_events server_conn_events = { PW_VERSION_PROTOCOL_NATIVE_CONNECTION_EVENTS, + .destroy = on_server_connection_destroy, .start = on_start, }; @@ -772,6 +781,12 @@ error: goto done; } +static void on_client_connection_destroy(void *data) +{ + struct client *impl = data; + spa_hook_remove(&impl->conn_listener); +} + static void on_need_flush(void *data) { struct client *impl = data; @@ -787,6 +802,7 @@ static void on_need_flush(void *data) static const struct pw_protocol_native_connection_events client_conn_events = { PW_VERSION_PROTOCOL_NATIVE_CONNECTION_EVENTS, + .destroy = on_client_connection_destroy, .need_flush = on_need_flush, }; diff --git a/src/modules/module-protocol-pulse/manager.c b/src/modules/module-protocol-pulse/manager.c index 24ffc57e9..af8304d17 100644 --- a/src/modules/module-protocol-pulse/manager.c +++ b/src/modules/module-protocol-pulse/manager.c @@ -127,8 +127,12 @@ static void object_destroy(struct object *o) struct manager *m = o->manager; spa_list_remove(&o->this.link); m->this.n_objects--; - if (o->this.proxy) + if (o->this.proxy) { + if (o->info->events) + spa_hook_remove(&o->object_listener); + spa_hook_remove(&o->proxy_listener); pw_proxy_destroy(o->this.proxy); + } free(o->this.type); if (o->this.props) pw_properties_free(o->this.props); diff --git a/src/modules/spa/module-device-factory.c b/src/modules/spa/module-device-factory.c index ad0b7c48e..4cbc81acd 100644 --- a/src/modules/spa/module-device-factory.c +++ b/src/modules/spa/module-device-factory.c @@ -188,6 +188,7 @@ static void factory_destroy(void *_data) struct factory_data *data = _data; struct device_data *nd; + spa_hook_remove(&data->factory_listener); spa_hook_remove(&data->module_listener); spa_list_consume(nd, &data->device_list, link) diff --git a/src/pipewire/context.c b/src/pipewire/context.c index 21981c39c..251bcf2e7 100644 --- a/src/pipewire/context.c +++ b/src/pipewire/context.c @@ -66,11 +66,6 @@ struct impl { }; -struct resource_data { - struct spa_hook resource_listener; - struct spa_hook object_listener; -}; - struct factory_entry { regex_t regex; char *lib; diff --git a/src/pipewire/core.c b/src/pipewire/core.c index e5f33a470..fb78f4efe 100644 --- a/src/pipewire/core.c +++ b/src/pipewire/core.c @@ -250,6 +250,9 @@ static void proxy_core_destroy(void *data) pw_log_debug(NAME" %p: free", core); pw_properties_free(core->properties); + + spa_hook_remove(&core->core_listener); + spa_hook_remove(&core->proxy_core_listener); } static const struct pw_proxy_events proxy_core_events = { diff --git a/src/pipewire/impl-client.c b/src/pipewire/impl-client.c index 243463376..ae33492d5 100644 --- a/src/pipewire/impl-client.c +++ b/src/pipewire/impl-client.c @@ -44,6 +44,7 @@ struct impl { #define pw_client_resource_permissions(r,...) pw_client_resource(r,permissions,0,__VA_ARGS__) struct resource_data { + struct pw_resource *resource; struct spa_hook resource_listener; struct spa_hook object_listener; struct pw_impl_client *client; @@ -123,8 +124,7 @@ static int error_resource(void *object, void *data) static int client_error(void *object, uint32_t id, int res, const char *error) { - struct pw_resource *resource = object; - struct resource_data *data = pw_resource_get_user_data(resource); + struct resource_data *data = object; struct pw_impl_client *client = data->client; struct error_data d = { id, res, error }; @@ -208,8 +208,7 @@ static int finish_register(struct pw_impl_client *client) static int client_update_properties(void *object, const struct spa_dict *props) { - struct pw_resource *resource = object; - struct resource_data *data = pw_resource_get_user_data(resource); + struct resource_data *data = object; struct pw_impl_client *client = data->client; int res = update_properties(client, props, true); finish_register(client); @@ -218,8 +217,8 @@ static int client_update_properties(void *object, const struct spa_dict *props) static int client_get_permissions(void *object, uint32_t index, uint32_t num) { - struct pw_resource *resource = object; - struct resource_data *data = pw_resource_get_user_data(resource); + struct resource_data *data = object; + struct pw_resource *resource = data->resource; struct pw_impl_client *client = data->client; struct impl *impl = SPA_CONTAINER_OF(client, struct impl, this); size_t len; @@ -238,8 +237,7 @@ static int client_get_permissions(void *object, uint32_t index, uint32_t num) static int client_update_permissions(void *object, uint32_t n_permissions, const struct pw_permission *permissions) { - struct pw_resource *resource = object; - struct resource_data *data = pw_resource_get_user_data(resource); + struct resource_data *data = object; struct pw_impl_client *client = data->client; return pw_impl_client_update_permissions(client, n_permissions, permissions); } @@ -254,7 +252,10 @@ static const struct pw_client_methods client_methods = { static void client_unbind_func(void *data) { - struct pw_resource *resource = data; + struct resource_data *d = data; + struct pw_resource *resource = d->resource; + spa_hook_remove(&d->resource_listener); + spa_hook_remove(&d->object_listener); if (resource->id == 1) resource->client->client_resource = NULL; } @@ -278,13 +279,14 @@ global_bind(void *_data, struct pw_impl_client *client, uint32_t permissions, goto error_resource; data = pw_resource_get_user_data(resource); + data->resource = resource; data->client = this; pw_resource_add_listener(resource, &data->resource_listener, - &resource_events, resource); + &resource_events, data); pw_resource_add_object_listener(resource, &data->object_listener, - &client_methods, resource); + &client_methods, data); pw_log_debug(NAME" %p: bound to %d", this, resource->id); pw_global_add_resource(global, resource); @@ -576,6 +578,8 @@ void pw_impl_client_destroy(struct pw_impl_client *client) pw_map_clear(&client->objects); pw_array_clear(&impl->permissions); + + spa_hook_remove(&impl->pool_listener); pw_mempool_destroy(client->pool); pw_properties_free(client->properties); diff --git a/src/pipewire/impl-core.c b/src/pipewire/impl-core.c index 41dd7c825..0b7d8f3da 100644 --- a/src/pipewire/impl-core.c +++ b/src/pipewire/impl-core.c @@ -35,6 +35,7 @@ #define NAME "impl-core" struct resource_data { + struct pw_resource *resource; struct spa_hook resource_listener; struct spa_hook object_listener; }; @@ -129,8 +130,11 @@ static const struct pw_registry_methods registry_methods = { static void destroy_registry_resource(void *object) { - struct pw_resource *resource = object; + struct resource_data *data = object; + struct pw_resource *resource = data->resource; spa_list_remove(&resource->link); + spa_hook_remove(&data->resource_listener); + spa_hook_remove(&data->object_listener); } static const struct pw_resource_events resource_events = { @@ -213,7 +217,7 @@ static int core_error(void *object, uint32_t id, int seq, int res, const char *m return 0; } -static struct pw_registry * core_get_registry(void *object, uint32_t version, size_t user_data_size) +static struct pw_registry *core_get_registry(void *object, uint32_t version, size_t user_data_size) { struct pw_resource *resource = object; struct pw_impl_client *client = resource->client; @@ -236,14 +240,15 @@ static struct pw_registry * core_get_registry(void *object, uint32_t version, si } data = pw_resource_get_user_data(registry_resource); + data->resource = registry_resource; pw_resource_add_listener(registry_resource, &data->resource_listener, &resource_events, - registry_resource); + data); pw_resource_add_object_listener(registry_resource, &data->object_listener, ®istry_methods, - registry_resource); + resource); spa_list_append(&context->registry_resource_list, ®istry_resource->link); @@ -446,7 +451,10 @@ void pw_impl_core_destroy(struct pw_impl_core *core) static void core_unbind_func(void *data) { - struct pw_resource *resource = data; + struct resource_data *d = data; + struct pw_resource *resource = d->resource; + spa_hook_remove(&d->resource_listener); + spa_hook_remove(&d->object_listener); if (resource->id == 0) resource->client->core_resource = NULL; } @@ -476,11 +484,11 @@ global_bind(void *_data, } data = pw_resource_get_user_data(resource); + data->resource = resource; pw_resource_add_listener(resource, &data->resource_listener, - &core_resource_events, - resource); + &core_resource_events, data); pw_resource_add_object_listener(resource, &data->object_listener, &core_methods, resource); diff --git a/src/pipewire/impl-device.c b/src/pipewire/impl-device.c index 3f7f1d950..63a5be3ad 100644 --- a/src/pipewire/impl-device.c +++ b/src/pipewire/impl-device.c @@ -190,6 +190,9 @@ void pw_impl_device_destroy(struct pw_impl_device *device) if (device->registered) spa_list_remove(&device->link); + if (device->device) { + spa_hook_remove(&device->listener); + } if (device->global) { spa_hook_remove(&device->global_listener); pw_global_destroy(device->global); @@ -216,6 +219,8 @@ static void resource_destroy(void *data) { struct resource_data *d = data; remove_busy_resource(d); + spa_hook_remove(&d->resource_listener); + spa_hook_remove(&d->object_listener); } static void resource_pong(void *data, int seq) diff --git a/src/pipewire/impl-node.c b/src/pipewire/impl-node.c index 2154aad89..8dd616d47 100644 --- a/src/pipewire/impl-node.c +++ b/src/pipewire/impl-node.c @@ -509,6 +509,8 @@ static void resource_destroy(void *data) { struct resource_data *d = data; remove_busy_resource(d); + spa_hook_remove(&d->resource_listener); + spa_hook_remove(&d->object_listener); } static void resource_pong(void *data, int seq) diff --git a/src/pipewire/impl-port.c b/src/pipewire/impl-port.c index bc8e71caa..f9a65a696 100644 --- a/src/pipewire/impl-port.c +++ b/src/pipewire/impl-port.c @@ -51,6 +51,7 @@ struct resource_data { struct pw_impl_port *port; struct pw_resource *resource; + struct spa_hook resource_listener; struct spa_hook object_listener; uint32_t subscribe_ids[MAX_PARAMS]; @@ -731,6 +732,18 @@ static const struct pw_port_methods port_methods = { .enum_params = port_enum_params }; +static void resource_destroy(void *data) +{ + struct resource_data *d = data; + spa_hook_remove(&d->resource_listener); + spa_hook_remove(&d->object_listener); +} + +static const struct pw_resource_events resource_events = { + PW_VERSION_RESOURCE_EVENTS, + .destroy = resource_destroy, +}; + static int global_bind(void *_data, struct pw_impl_client *client, uint32_t permissions, uint32_t version, uint32_t id) @@ -751,6 +764,9 @@ global_bind(void *_data, struct pw_impl_client *client, uint32_t permissions, data->port = this; data->resource = resource; + pw_resource_add_listener(resource, + &data->resource_listener, + &resource_events, data); pw_resource_add_object_listener(resource, &data->object_listener, &port_methods, data); diff --git a/src/tools/pw-cli.c b/src/tools/pw-cli.c index 82bc72ea7..feb67c0d1 100644 --- a/src/tools/pw-cli.c +++ b/src/tools/pw-cli.c @@ -432,6 +432,10 @@ static void on_core_destroy(void *_data) spa_list_remove(&rd->link); + spa_hook_remove(&rd->core_listener); + spa_hook_remove(&rd->registry_listener); + spa_hook_remove(&rd->proxy_core_listener); + pw_map_remove(&data->vars, rd->id); pw_map_for_each(&rd->globals, destroy_global, rd); pw_map_clear(&rd->globals); @@ -1111,6 +1115,9 @@ destroy_proxy (void *data) { struct proxy_data *pd = data; + spa_hook_remove(&pd->proxy_listener); + spa_hook_remove(&pd->object_listener); + if (pd->info == NULL) return;