From 6d4db647674dc249a2683e9dbab6def36ec51c29 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Thu, 12 Jan 2017 14:57:07 +0100 Subject: [PATCH] Use refcounting for async shutdown fix some memory leaks --- pinos/client/introspect.c | 2 - pinos/client/introspect.h | 5 +- pinos/client/mapper.c | 6 +- pinos/client/stream.c | 10 +-- pinos/modules/module-access.c | 10 ++- pinos/modules/module-autolink.c | 5 +- pinos/modules/module-protocol-dbus.c | 2 +- pinos/modules/module-protocol-native.c | 19 +++-- pinos/modules/spa/module.c | 1 + pinos/server/client-node.c | 86 +++++++++++-------- pinos/server/client.c | 39 ++++----- pinos/server/client.h | 3 +- pinos/server/core.c | 47 +++++------ pinos/server/link.c | 112 +++++++++++-------------- pinos/server/link.h | 2 + pinos/server/module.h | 6 +- pinos/server/node.c | 70 ++++++---------- pinos/server/node.h | 2 + pinos/server/port.c | 17 +--- pinos/server/resource.c | 30 ++----- pinos/server/resource.h | 2 +- 21 files changed, 216 insertions(+), 260 deletions(-) diff --git a/pinos/client/introspect.c b/pinos/client/introspect.c index 7d5f4a59b..8374e7eb3 100644 --- a/pinos/client/introspect.c +++ b/pinos/client/introspect.c @@ -42,8 +42,6 @@ pinos_node_state_as_string (PinosNodeState state) return "creating"; case PINOS_NODE_STATE_SUSPENDED: return "suspended"; - case PINOS_NODE_STATE_INITIALIZING: - return "initializing"; case PINOS_NODE_STATE_IDLE: return "idle"; case PINOS_NODE_STATE_RUNNING: diff --git a/pinos/client/introspect.h b/pinos/client/introspect.h index 7ef95a264..da14cb882 100644 --- a/pinos/client/introspect.h +++ b/pinos/client/introspect.h @@ -57,9 +57,8 @@ enum _PinosNodeState { PINOS_NODE_STATE_ERROR = -1, PINOS_NODE_STATE_CREATING = 0, PINOS_NODE_STATE_SUSPENDED = 1, - PINOS_NODE_STATE_INITIALIZING = 2, - PINOS_NODE_STATE_IDLE = 3, - PINOS_NODE_STATE_RUNNING = 4, + PINOS_NODE_STATE_IDLE = 2, + PINOS_NODE_STATE_RUNNING = 3, }; const char * pinos_node_state_as_string (PinosNodeState state); diff --git a/pinos/client/mapper.c b/pinos/client/mapper.c index f0cca32f9..f0acba99b 100644 --- a/pinos/client/mapper.c +++ b/pinos/client/mapper.c @@ -55,7 +55,11 @@ id_map_get_uri (SpaIDMap *map, uint32_t id) IDMap *this = SPA_CONTAINER_OF (map, IDMap, map); if (id == SPA_ID_INVALID) return NULL; - return pinos_map_lookup (&this->uris, id); + + if (SPA_LIKELY (pinos_map_check_id (&this->uris, id))) + return pinos_map_lookup_unchecked (&this->uris, id); + + return NULL; } static IDMap default_id_map = { diff --git a/pinos/client/stream.c b/pinos/client/stream.c index 31fae07ed..68812e6a1 100644 --- a/pinos/client/stream.c +++ b/pinos/client/stream.c @@ -844,8 +844,6 @@ pinos_stream_connect (PinosStream *stream, { PinosStreamImpl *impl = SPA_CONTAINER_OF (stream, PinosStreamImpl, this); PinosMessageCreateClientNode ccn; - SpaDict dict; - SpaDictItem items[1]; impl->direction = direction == PINOS_DIRECTION_INPUT ? SPA_DIRECTION_INPUT : SPA_DIRECTION_OUTPUT; impl->port_id = 0; @@ -866,7 +864,7 @@ pinos_stream_connect (PinosStream *stream, impl->node_proxy = pinos_proxy_new (stream->context, SPA_ID_INVALID, - 0); + stream->context->uri.client_node); pinos_proxy_set_dispatch (impl->node_proxy, stream_dispatch_func, @@ -874,11 +872,7 @@ pinos_stream_connect (PinosStream *stream, ccn.seq = ++impl->seq; ccn.name = "client-node"; - dict.n_items = 1; - dict.items = items; - items[0].key = "pinos.target.node"; - items[0].value = port_path; - ccn.props = &dict; + ccn.props = &stream->properties->dict; ccn.new_id = impl->node_proxy->id; pinos_proxy_send_message (stream->context->core_proxy, diff --git a/pinos/modules/module-access.c b/pinos/modules/module-access.c index 3a41b5527..b90eee304 100644 --- a/pinos/modules/module-access.c +++ b/pinos/modules/module-access.c @@ -42,8 +42,16 @@ check_global_owner (PinosCore *core, PinosGlobal *global; global = pinos_map_lookup (&core->objects, id); + if (global == NULL) + return false; - return (global && global->owner == client); + if (global->owner == NULL) + return true; + + if (global->owner->ucred.uid == client->ucred.uid) + return true; + + return false; } static void diff --git a/pinos/modules/module-autolink.c b/pinos/modules/module-autolink.c index 3e0901dad..99d21fedb 100644 --- a/pinos/modules/module-autolink.c +++ b/pinos/modules/module-autolink.c @@ -82,7 +82,8 @@ try_link_port (PinosNode *node, PinosPort *port, ModuleImpl *impl) error: { - pinos_node_update_state (node, PINOS_NODE_STATE_ERROR, error); + pinos_log_error ("module %p: can't link node '%s'", impl, error); + free (error); return; } } @@ -271,6 +272,6 @@ module_destroy (ModuleImpl *impl) bool pinos__module_init (PinosModule * module, const char * args) { - module_new (module->core, NULL); + module->user_data = module_new (module->core, NULL); return true; } diff --git a/pinos/modules/module-protocol-dbus.c b/pinos/modules/module-protocol-dbus.c index a07bb5dc0..6d530ec21 100644 --- a/pinos/modules/module-protocol-dbus.c +++ b/pinos/modules/module-protocol-dbus.c @@ -251,7 +251,7 @@ client_new (PinosProtocolDBus *impl, PinosProtocolDBusClient *this; PinosClient *client; - client = pinos_client_new (impl->core, NULL); + client = pinos_client_new (impl->core, NULL, NULL); if ((this = (PinosProtocolDBusClient *) find_object (impl, client))) { pinos_client1_set_sender (this->parent.iface, sender); diff --git a/pinos/modules/module-protocol-native.c b/pinos/modules/module-protocol-native.c index 46bc25040..48eceab81 100644 --- a/pinos/modules/module-protocol-native.c +++ b/pinos/modules/module-protocol-native.c @@ -180,6 +180,7 @@ client_new (PinosProtocolNative *impl, PinosProtocolNativeClient *this; PinosClient *client; socklen_t len; + struct ucred ucred, *ucredp; this = calloc (1, sizeof (PinosProtocolNativeClient)); if (this == NULL) @@ -200,7 +201,15 @@ client_new (PinosProtocolNative *impl, if (this->connection == NULL) goto no_connection; - client = pinos_client_new (impl->core, NULL); + len = sizeof (ucred); + if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len) < 0) { + pinos_log_error ("no peercred: %m"); + ucredp = NULL; + } else { + ucredp = &ucred; + } + + client = pinos_client_new (impl->core, ucredp, NULL); if (client == NULL) goto no_client; @@ -210,14 +219,6 @@ client_new (PinosProtocolNative *impl, client_send_func, this); - len = sizeof (client->ucred); - if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &client->ucred, &len) < 0) { - client->ucred_valid = false; - pinos_log_error ("no peercred: %m"); - } else { - client->ucred_valid = true; - } - spa_list_insert (impl->client_list.prev, &this->link); pinos_global_bind (impl->core->global, diff --git a/pinos/modules/spa/module.c b/pinos/modules/spa/module.c index 2374a0b0b..991b78887 100644 --- a/pinos/modules/spa/module.c +++ b/pinos/modules/spa/module.c @@ -113,6 +113,7 @@ pinos__module_init (PinosModule * module, const char * args) } } free (argv); + pinos_free_strv (tmp_argv); } pinos_spa_monitor_load (module->core, "build/spa/plugins/alsa/libspa-alsa.so", "alsa-monitor"); diff --git a/pinos/server/client-node.c b/pinos/server/client-node.c index 0d7d04f38..752e0a582 100644 --- a/pinos/server/client-node.c +++ b/pinos/server/client-node.c @@ -119,6 +119,7 @@ typedef struct SpaProxy proxy; + PinosListener node_free; PinosListener transport_changed; PinosListener loop_changed; PinosListener global_added; @@ -177,6 +178,9 @@ spa_proxy_node_send_command (SpaNode *node, this = SPA_CONTAINER_OF (node, SpaProxy, node); + if (this->resource == NULL) + return SPA_RESULT_OK; + switch (command->type) { case SPA_NODE_COMMAND_INVALID: return SPA_RESULT_INVALID_COMMAND; @@ -200,7 +204,6 @@ spa_proxy_node_send_command (SpaNode *node, uint8_t cmd = PINOS_TRANSPORT_CMD_NEED_DATA; write (this->data_source.fd, &cmd, 1); } - res = SPA_RESULT_RETURN_ASYNC (cnc.seq); break; } @@ -295,7 +298,7 @@ spa_proxy_node_get_port_ids (SpaNode *node, } static void -do_update_port (SpaProxy *this, +do_update_port (SpaProxy *this, PinosMessagePortUpdate *pu) { SpaProxyPort *port; @@ -312,17 +315,22 @@ do_update_port (SpaProxy *this, for (i = 0; i < port->n_formats; i++) free (port->formats[i]); port->n_formats = pu->n_possible_formats; - port->formats = realloc (port->formats, port->n_formats * sizeof (SpaFormat *)); + if (port->n_formats) + port->formats = realloc (port->formats, port->n_formats * sizeof (SpaFormat *)); + else { + free (port->formats); + port->formats = NULL; + } for (i = 0; i < port->n_formats; i++) { size = pinos_serialize_format_get_size (pu->possible_formats[i]); - port->formats[i] = pinos_serialize_format_copy_into (malloc (size), pu->possible_formats[i]); + port->formats[i] = size ? pinos_serialize_format_copy_into (malloc (size), pu->possible_formats[i]) : NULL; } } if (pu->change_mask & PINOS_MESSAGE_PORT_UPDATE_FORMAT) { if (port->format) free (port->format); size = pinos_serialize_format_get_size (pu->format); - port->format = pinos_serialize_format_copy_into (malloc (size), pu->format); + port->format = size ? pinos_serialize_format_copy_into (malloc (size), pu->format) : NULL; } if (pu->change_mask & PINOS_MESSAGE_PORT_UPDATE_PROPS) { @@ -332,7 +340,7 @@ do_update_port (SpaProxy *this, if (port->info) free (port->info); size = pinos_serialize_port_info_get_size (pu->info); - port->info = pinos_serialize_port_info_copy_into (malloc (size), pu->info); + port->info = size ? pinos_serialize_port_info_copy_into (malloc (size), pu->info) : NULL; } if (!port->valid) { @@ -482,6 +490,9 @@ spa_proxy_node_port_set_format (SpaNode *node, if (!CHECK_PORT (this, direction, port_id)) return SPA_RESULT_INVALID_PORT; + if (this->resource == NULL) + return SPA_RESULT_OK; + sf.seq = this->seq++; sf.direction = direction; sf.port_id = port_id; @@ -641,6 +652,11 @@ spa_proxy_node_port_use_buffers (SpaNode *node, mb = NULL; } + port->n_buffers = n_buffers; + + if (this->resource == NULL) + return SPA_RESULT_OK; + n_mem = 0; for (i = 0; i < n_buffers; i++) { ProxyBuffer *b = &port->buffers[i]; @@ -715,8 +731,6 @@ spa_proxy_node_port_use_buffers (SpaNode *node, } } - port->n_buffers = n_buffers; - ub.seq = this->seq++; ub.direction = direction; ub.port_id = port_id; @@ -1169,6 +1183,9 @@ on_transport_changed (PinosListener *listener, PinosTransportInfo info; PinosMessageTransportUpdate tu; + if (this->resource == NULL) + return; + pinos_transport_get_info (node->transport, &info); tu.memfd = info.memfd; @@ -1194,6 +1211,7 @@ on_global_added (PinosListener *listener, PinosGlobal *global) { PinosClientNodeImpl *impl = SPA_CONTAINER_OF (listener, PinosClientNodeImpl, global_added); + if (global->object == impl->this.node) global->owner = impl->this.client; } @@ -1222,7 +1240,25 @@ proxy_clear (SpaProxy *this) static void client_node_resource_destroy (PinosResource *resource) { - pinos_client_node_destroy (resource->object); + PinosClientNode *this = resource->object; + PinosClientNodeImpl *impl = SPA_CONTAINER_OF (this, PinosClientNodeImpl, this); + + impl->proxy.resource = this->resource = NULL; + pinos_client_node_destroy (this); +} + +static void +on_node_free (PinosListener *listener, + PinosNode *node) +{ + PinosClientNodeImpl *impl = SPA_CONTAINER_OF (listener, PinosClientNodeImpl, node_free); + + pinos_log_debug ("client-node %p: free", &impl->this); + proxy_clear (&impl->proxy); + + if (impl->data_fd != -1) + close (impl->data_fd); + free (impl); } /** @@ -1249,6 +1285,8 @@ pinos_client_node_new (PinosClient *client, return NULL; this = &impl->this; + this->client = client; + impl->core = client->core; impl->data_fd = -1; pinos_log_debug ("client-node %p: new", impl); @@ -1277,6 +1315,10 @@ pinos_client_node_new (PinosClient *client, impl->proxy.resource = this->resource; + pinos_signal_add (&this->node->free_signal, + &impl->node_free, + on_node_free); + pinos_signal_add (&this->node->transport_changed, &impl->transport_changed, on_transport_changed); @@ -1303,24 +1345,6 @@ error_no_node: return NULL; } -static void -on_node_remove (void *object, - void *data, - SpaResult res, - uint32_t id) -{ - PinosClientNode *this = object; - PinosClientNodeImpl *impl = SPA_CONTAINER_OF (this, PinosClientNodeImpl, this); - - pinos_log_debug ("client-node %p: finalize", this); - proxy_clear (&impl->proxy); - - if (impl->data_fd != -1) - close (impl->data_fd); - free (impl); -} - - void pinos_client_node_destroy (PinosClientNode * this) { @@ -1330,14 +1354,10 @@ pinos_client_node_destroy (PinosClientNode * this) pinos_signal_emit (&this->destroy_signal, this); pinos_signal_remove (&impl->global_added); + pinos_signal_remove (&impl->loop_changed); + pinos_signal_remove (&impl->transport_changed); pinos_node_destroy (this->node); - - pinos_main_loop_defer (this->node->core->main_loop, - this, - SPA_RESULT_WAIT_SYNC, - (PinosDeferFunc) on_node_remove, - this); } /** diff --git a/pinos/server/client.c b/pinos/server/client.c index 3b11c0e3f..96ffe7fee 100644 --- a/pinos/server/client.c +++ b/pinos/server/client.c @@ -110,6 +110,7 @@ no_mem: */ PinosClient * pinos_client_new (PinosCore *core, + struct ucred *ucred, PinosProperties *properties) { PinosClient *this; @@ -123,6 +124,8 @@ pinos_client_new (PinosCore *core, this = &impl->this; this->core = core; + if ((this->ucred_valid = (ucred != NULL))) + this->ucred = *ucred; this->properties = properties; spa_list_init (&this->resource_list); @@ -142,23 +145,6 @@ pinos_client_new (PinosCore *core, return this; } -static void -sync_destroy (void *object, - void *data, - SpaResult res, - uint32_t id) -{ - PinosClientImpl *impl = SPA_CONTAINER_OF (object, PinosClientImpl, this); - PinosClient *client = &impl->this; - - pinos_log_debug ("client %p: sync destroy", impl); - - if (client->properties) - pinos_properties_free (client->properties); - - free (impl); -} - static void destroy_resource (void *object, void *data) @@ -176,23 +162,26 @@ void pinos_client_destroy (PinosClient * client) { PinosResource *resource, *tmp; + PinosClientImpl *impl = SPA_CONTAINER_OF (client, PinosClientImpl, this); pinos_log_debug ("client %p: destroy", client); pinos_signal_emit (&client->destroy_signal, client); - pinos_map_for_each (&client->objects, destroy_resource, client); - - pinos_global_destroy (client->global); spa_list_remove (&client->link); + pinos_global_destroy (client->global); spa_list_for_each_safe (resource, tmp, &client->resource_list, link) pinos_resource_destroy (resource); - pinos_main_loop_defer (client->core->main_loop, - client, - SPA_RESULT_WAIT_SYNC, - sync_destroy, - client); + pinos_map_for_each (&client->objects, destroy_resource, client); + + pinos_log_debug ("client %p: free", impl); + pinos_map_clear (&client->objects); + + if (client->properties) + pinos_properties_free (client->properties); + + free (impl); } void diff --git a/pinos/server/client.h b/pinos/server/client.h index 0c515e488..98b801944 100644 --- a/pinos/server/client.h +++ b/pinos/server/client.h @@ -62,10 +62,11 @@ struct _PinosClient { SpaList resource_list; PINOS_SIGNAL (destroy_signal, (PinosListener *listener, - PinosClient *client)); + PinosClient *client)); }; PinosClient * pinos_client_new (PinosCore *core, + struct ucred *ucred, PinosProperties *properties); void pinos_client_destroy (PinosClient *client); diff --git a/pinos/server/core.c b/pinos/server/core.c index c9f29eaf0..2ba381865 100644 --- a/pinos/server/core.c +++ b/pinos/server/core.c @@ -192,6 +192,13 @@ no_mem: return SPA_RESULT_NO_MEMORY; } +static void +core_unbind_func (void *data) +{ + PinosResource *resource = data; + resource->client->core_resource = NULL; +} + static SpaResult core_bind_func (PinosGlobal *global, PinosClient *client, @@ -207,7 +214,7 @@ core_bind_func (PinosGlobal *global, id, global->type, global->object, - NULL); + core_unbind_func); if (resource == NULL) goto no_mem; @@ -310,10 +317,14 @@ pinos_core_destroy (PinosCore *core) { PinosCoreImpl *impl = SPA_CONTAINER_OF (core, PinosCoreImpl, this); + pinos_log_debug ("core %p: destroy", core); pinos_signal_emit (&core->destroy_signal, core); pinos_data_loop_destroy (core->data_loop); + pinos_map_clear (&core->objects); + + pinos_log_debug ("core %p: free", core); free (impl); } @@ -350,10 +361,11 @@ pinos_core_add_global (PinosCore *core, spa_list_insert (core->global_list.prev, &this->link); pinos_signal_emit (&core->global_added, core, this); - pinos_log_debug ("global %p: new %u", this, this->id); - ng.id = this->id; ng.type = spa_id_map_get_uri (core->uri.map, this->type); + + pinos_log_debug ("global %p: new %u %s", this, ng.id, ng.type); + spa_list_for_each (registry, &core->registry_resource_list, link) { pinos_resource_send_message (registry, PINOS_MESSAGE_NOTIFY_GLOBAL, @@ -384,18 +396,6 @@ pinos_global_bind (PinosGlobal *global, return res; } -static void -sync_destroy (void *object, - void *data, - SpaResult res, - uint32_t id) -{ - PinosGlobal *global = object; - - pinos_log_debug ("global %p: sync destroy", global); - free (global); -} - void pinos_global_destroy (PinosGlobal *global) { @@ -406,11 +406,6 @@ pinos_global_destroy (PinosGlobal *global) pinos_log_debug ("global %p: destroy %u", global, global->id); pinos_signal_emit (&global->destroy_signal, global); - pinos_map_remove (&core->objects, global->id); - - spa_list_remove (&global->link); - pinos_signal_emit (&core->global_removed, core, global); - ng.id = global->id; spa_list_for_each (registry, &core->registry_resource_list, link) { pinos_resource_send_message (registry, @@ -419,11 +414,13 @@ pinos_global_destroy (PinosGlobal *global) true); } - pinos_main_loop_defer (core->main_loop, - global, - SPA_RESULT_WAIT_SYNC, - sync_destroy, - global); + pinos_map_remove (&core->objects, global->id); + + spa_list_remove (&global->link); + pinos_signal_emit (&core->global_removed, core, global); + + pinos_log_debug ("global %p: free", global); + free (global); } PinosPort * diff --git a/pinos/server/link.c b/pinos/server/link.c index 14421cd2b..f51fc366e 100644 --- a/pinos/server/link.c +++ b/pinos/server/link.c @@ -32,6 +32,8 @@ typedef struct { PinosLink this; + int refcount; + uint32_t seq; SpaFormat **format_filter; @@ -648,25 +650,12 @@ on_output_async_complete_notify (PinosListener *listener, pinos_main_loop_defer_complete (this->core->main_loop, impl, seq, res); } -static void -on_port_unlinked (PinosPort *port, PinosLink *this, SpaResult res, uint32_t id) -{ - pinos_signal_emit (&this->core->port_unlinked, this, port); - - if (this->input == NULL || this->output == NULL) { - pinos_link_update_state (this, PINOS_LINK_STATE_UNLINKED, NULL); - pinos_link_destroy (this); - } - -} - static void on_port_destroy (PinosLink *this, PinosPort *port) { PinosLinkImpl *impl = (PinosLinkImpl *) this; PinosPort *other; - SpaResult res = SPA_RESULT_OK; if (port == this->input) { pinos_log_debug ("link %p: input port destroyed %p", this, port); @@ -691,11 +680,10 @@ on_port_destroy (PinosLink *this, pinos_port_clear_buffers (other); } - pinos_main_loop_defer (this->core->main_loop, - port, - res, - (PinosDeferFunc) on_port_unlinked, - this); + pinos_signal_emit (&this->core->port_unlinked, this, port); + + pinos_link_update_state (this, PINOS_LINK_STATE_UNLINKED, NULL); + pinos_link_destroy (this); } static void @@ -749,11 +737,31 @@ link_dispatch_func (void *object, return SPA_RESULT_OK; } +static void +pinos_link_free (PinosLink *link) +{ + PinosLinkImpl *impl = SPA_CONTAINER_OF (link, PinosLinkImpl, this); + + pinos_log_debug ("link %p: free", link); + pinos_signal_emit (&link->free_signal, link); + + if (impl->allocated) + pinos_memblock_free (&impl->buffer_mem); + + free (impl); +} + static void link_unbind_func (void *data) { PinosResource *resource = data; + PinosLink *this = resource->object; + PinosLinkImpl *impl = SPA_CONTAINER_OF (this, PinosLinkImpl, this); + spa_list_remove (&resource->link); + + if (--impl->refcount == 0) + pinos_link_free (this); } static SpaResult @@ -763,6 +771,7 @@ link_bind_func (PinosGlobal *global, uint32_t id) { PinosLink *this = global->object; + PinosLinkImpl *impl = SPA_CONTAINER_OF (this, PinosLinkImpl, this); PinosResource *resource; PinosMessageLinkInfo m; PinosLinkInfo info; @@ -775,6 +784,8 @@ link_bind_func (PinosGlobal *global, if (resource == NULL) goto no_mem; + impl->refcount++; + pinos_resource_set_dispatch (resource, link_dispatch_func, global); @@ -790,6 +801,7 @@ link_bind_func (PinosGlobal *global, info.output_port_id = this->output ? this->output->port_id : -1; info.input_node_id = this->input ? this->input->node->global->id : -1; info.input_port_id = this->input ? this->input->port_id : -1; + return pinos_resource_send_message (resource, PINOS_MESSAGE_LINK_INFO, &m, @@ -821,12 +833,14 @@ pinos_link_new (PinosCore *core, this->core = core; this->properties = properties; this->state = PINOS_LINK_STATE_INIT; + impl->refcount = 1; this->input = input; this->output = output; spa_list_init (&this->resource_list); pinos_signal_init (&this->destroy_signal); + pinos_signal_init (&this->free_signal); impl->format_filter = format_filter; @@ -884,6 +898,7 @@ do_link_remove_done (SpaLoop *loop, void *user_data) { PinosLink *this = user_data; + PinosLinkImpl *impl = SPA_CONTAINER_OF (this, PinosLinkImpl, this); if (this->input) { spa_list_remove (&this->input_link); @@ -907,11 +922,8 @@ do_link_remove_done (SpaLoop *loop, clear_port_buffers (this, this->output); this->output = NULL; } - - pinos_main_loop_defer_complete (this->core->main_loop, - this, - seq, - SPA_RESULT_OK); + if (--impl->refcount == 0) + pinos_link_free (this); return SPA_RESULT_OK; } @@ -945,22 +957,6 @@ do_link_remove (SpaLoop *loop, return res; } -static void -sync_destroy (void *object, - void *data, - SpaResult res, - uint32_t id) -{ - PinosLinkImpl *impl = SPA_CONTAINER_OF (object, PinosLinkImpl, this); - - pinos_log_debug ("link %p: sync destroy", impl); - - if (impl->allocated) - pinos_memblock_free (&impl->buffer_mem); - - free (impl); -} - /** * pinos_link_destroy: * @link: a #PinosLink @@ -970,7 +966,6 @@ sync_destroy (void *object, void pinos_link_destroy (PinosLink * this) { - SpaResult res = SPA_RESULT_OK; PinosLinkImpl *impl = SPA_CONTAINER_OF (this, PinosLinkImpl, this); PinosResource *resource, *tmp; @@ -987,31 +982,26 @@ pinos_link_destroy (PinosLink * this) pinos_signal_remove (&impl->input_port_destroy); pinos_signal_remove (&impl->input_async_complete); - res = pinos_loop_invoke (this->input->node->data_loop->loop, - do_link_remove, - impl->seq++, - 0, - NULL, - this); - - pinos_main_loop_defer (this->core->main_loop, this, res, NULL, NULL); + impl->refcount++; + pinos_loop_invoke (this->input->node->data_loop->loop, + do_link_remove, + impl->seq++, + 0, + NULL, + this); } if (this->output) { pinos_signal_remove (&impl->output_port_destroy); pinos_signal_remove (&impl->output_async_complete); - res = pinos_loop_invoke (this->output->node->data_loop->loop, - do_link_remove, - impl->seq++, - 0, - NULL, - this); - pinos_main_loop_defer (this->core->main_loop, this, res, NULL, NULL); + impl->refcount++; + pinos_loop_invoke (this->output->node->data_loop->loop, + do_link_remove, + impl->seq++, + 0, + NULL, + this); } - - pinos_main_loop_defer (this->core->main_loop, - this, - SPA_RESULT_WAIT_SYNC, - sync_destroy, - this); + if (--impl->refcount == 0) + pinos_link_free (this); } diff --git a/pinos/server/link.h b/pinos/server/link.h index d9f522e75..880fdf87c 100644 --- a/pinos/server/link.h +++ b/pinos/server/link.h @@ -51,6 +51,8 @@ struct _PinosLink { PINOS_SIGNAL (destroy_signal, (PinosListener *, PinosLink *)); + PINOS_SIGNAL (free_signal, (PinosListener *, + PinosLink *)); SpaList resource_list; diff --git a/pinos/server/module.h b/pinos/server/module.h index 9fd78ee24..f500fa01b 100644 --- a/pinos/server/module.h +++ b/pinos/server/module.h @@ -30,14 +30,16 @@ extern "C" { typedef struct _PinosModule PinosModule; struct _PinosModule { - PinosCore *core; - SpaList link; + PinosCore *core; + SpaList link; PinosGlobal *global; char *name; char *filename; char *args; + void *user_data; + PINOS_SIGNAL (destroy_signal, (PinosListener *listener, PinosModule *module)); }; diff --git a/pinos/server/node.c b/pinos/server/node.c index 865fedb2f..ccaf26f03 100644 --- a/pinos/server/node.c +++ b/pinos/server/node.c @@ -461,10 +461,9 @@ init_complete (PinosNode *this) pinos_log_debug ("node %p: init completed", this); impl->async_init = false; - spa_list_insert (this->core->node_list.prev, &this->link); - pinos_node_update_state (this, PINOS_NODE_STATE_SUSPENDED, NULL); + spa_list_insert (this->core->node_list.prev, &this->link); this->global = pinos_core_add_global (this->core, NULL, this->core->uri.node, @@ -512,6 +511,7 @@ pinos_node_new (PinosCore *core, pinos_log_warn ("node %p: error setting callback", this); pinos_signal_init (&this->destroy_signal); + pinos_signal_init (&this->free_signal); pinos_signal_init (&this->async_complete); pinos_signal_init (&this->transport_changed); pinos_signal_init (&this->loop_changed); @@ -564,6 +564,7 @@ do_node_remove_done (SpaLoop *loop, void *user_data) { PinosNode *this = user_data; + PinosNodeImpl *impl = SPA_CONTAINER_OF (this, PinosNodeImpl, this); PinosPort *port, *tmp; pinos_log_debug ("node %p: remove done, destroy ports", this); @@ -573,10 +574,21 @@ do_node_remove_done (SpaLoop *loop, spa_list_for_each_safe (port, tmp, &this->output_ports, link) pinos_port_destroy (port); - pinos_main_loop_defer_complete (this->core->main_loop, - this, - seq, - SPA_RESULT_OK); + pinos_log_debug ("node %p: free", this); + pinos_signal_emit (&this->free_signal, this); + + if (this->transport) + pinos_transport_destroy (this->transport); + if (this->input_port_map) + free (this->input_port_map); + if (this->output_port_map) + free (this->output_port_map); + + free (this->name); + free (this->error); + if (this->properties) + pinos_properties_free (this->properties); + free (impl); return SPA_RESULT_OK; } @@ -620,24 +632,6 @@ do_node_remove (SpaLoop *loop, return res; } -static void -sync_destroy (void *object, - void *data, - SpaResult res, - uint32_t id) -{ - PinosNode *this = object; - PinosNodeImpl *impl = SPA_CONTAINER_OF (this, PinosNodeImpl, this); - - pinos_log_debug ("node %p: sync destroy", this); - - free (this->name); - free (this->error); - if (this->properties) - pinos_properties_free (this->properties); - free (impl); -} - /** * pinos_node_destroy: * @node: a #PinosNode @@ -648,7 +642,6 @@ sync_destroy (void *object, void pinos_node_destroy (PinosNode * this) { - SpaResult res; PinosNodeImpl *impl = SPA_CONTAINER_OF (this, PinosNodeImpl, this); PinosResource *resource, *tmp; @@ -661,24 +654,12 @@ pinos_node_destroy (PinosNode * this) spa_list_for_each_safe (resource, tmp, &this->resource_list, link) pinos_resource_destroy (resource); - res = pinos_loop_invoke (this->data_loop->loop, - do_node_remove, - impl->seq++, - 0, - NULL, - this); - - pinos_main_loop_defer (this->core->main_loop, - this, - res, - NULL, - NULL); - - pinos_main_loop_defer (this->core->main_loop, - this, - SPA_RESULT_WAIT_SYNC, - sync_destroy, - this); + pinos_loop_invoke (this->data_loop->loop, + do_node_remove, + impl->seq++, + 0, + NULL, + this); } /** @@ -771,9 +752,6 @@ pinos_node_set_state (PinosNode *node, res = suspend_node (node); break; - case PINOS_NODE_STATE_INITIALIZING: - break; - case PINOS_NODE_STATE_IDLE: res = pause_node (node); break; diff --git a/pinos/server/node.h b/pinos/server/node.h index ea26b4dd5..d32735e1a 100644 --- a/pinos/server/node.h +++ b/pinos/server/node.h @@ -79,6 +79,8 @@ struct _PinosNode { PINOS_SIGNAL (destroy_signal, (PinosListener *listener, PinosNode *object)); + PINOS_SIGNAL (free_signal, (PinosListener *listener, + PinosNode *object)); PINOS_SIGNAL (async_complete, (PinosListener *listener, PinosNode *node, diff --git a/pinos/server/port.c b/pinos/server/port.c index 9b1953c25..94a9581ed 100644 --- a/pinos/server/port.c +++ b/pinos/server/port.c @@ -56,17 +56,6 @@ pinos_port_new (PinosNode *node, return this; } -static void -sync_destroy (void *object, - void *data, - SpaResult res, - uint32_t id) -{ - PinosPort *port = object; - - free (port); -} - void pinos_port_destroy (PinosPort *port) { @@ -83,11 +72,7 @@ pinos_port_destroy (PinosPort *port) port->buffers = NULL; port->n_buffers = 0; - pinos_main_loop_defer (port->node->core->main_loop, - port, - SPA_RESULT_WAIT_SYNC, - sync_destroy, - port); + free (port); } static SpaResult diff --git a/pinos/server/resource.c b/pinos/server/resource.c index bde2f7542..9de2c1e81 100644 --- a/pinos/server/resource.c +++ b/pinos/server/resource.c @@ -59,28 +59,12 @@ pinos_resource_new (PinosClient *client, return this; } -static void -sync_destroy (void *object, - void *data, - SpaResult res, - uint32_t id) -{ - PinosResource *resource = object; - pinos_log_debug ("resource %p: sync destroy", resource); - free (resource); -} - -SpaResult +void pinos_resource_destroy (PinosResource *resource) { pinos_log_debug ("resource %p: destroy", resource); pinos_signal_emit (&resource->destroy_signal, resource); - pinos_map_remove (&resource->client->objects, resource->id); - - if (resource->destroy) - resource->destroy (resource); - if (resource->client->core_resource) { PinosMessageRemoveId m; m.id = resource->id; @@ -90,13 +74,13 @@ pinos_resource_destroy (PinosResource *resource) true); } - pinos_main_loop_defer (resource->core->main_loop, - resource, - SPA_RESULT_WAIT_SYNC, - sync_destroy, - resource); + pinos_map_remove (&resource->client->objects, resource->id); - return SPA_RESULT_OK; + if (resource->destroy) + resource->destroy (resource); + + pinos_log_debug ("resource %p: free", resource); + free (resource); } void diff --git a/pinos/server/resource.h b/pinos/server/resource.h index f190660af..3166eb7ff 100644 --- a/pinos/server/resource.h +++ b/pinos/server/resource.h @@ -62,7 +62,7 @@ PinosResource * pinos_resource_new (PinosClient *client, uint32_t type, void *object, PinosDestroy destroy); -SpaResult pinos_resource_destroy (PinosResource *resource); +void pinos_resource_destroy (PinosResource *resource); void pinos_resource_set_dispatch (PinosResource *resource, PinosDispatchFunc func,