Use refcounting for async shutdown

fix some memory leaks
This commit is contained in:
Wim Taymans 2017-01-12 14:57:07 +01:00
parent ee0aa6a2ac
commit 6d4db64767
21 changed files with 216 additions and 260 deletions

View file

@ -42,8 +42,6 @@ pinos_node_state_as_string (PinosNodeState state)
return "creating"; return "creating";
case PINOS_NODE_STATE_SUSPENDED: case PINOS_NODE_STATE_SUSPENDED:
return "suspended"; return "suspended";
case PINOS_NODE_STATE_INITIALIZING:
return "initializing";
case PINOS_NODE_STATE_IDLE: case PINOS_NODE_STATE_IDLE:
return "idle"; return "idle";
case PINOS_NODE_STATE_RUNNING: case PINOS_NODE_STATE_RUNNING:

View file

@ -57,9 +57,8 @@ enum _PinosNodeState {
PINOS_NODE_STATE_ERROR = -1, PINOS_NODE_STATE_ERROR = -1,
PINOS_NODE_STATE_CREATING = 0, PINOS_NODE_STATE_CREATING = 0,
PINOS_NODE_STATE_SUSPENDED = 1, PINOS_NODE_STATE_SUSPENDED = 1,
PINOS_NODE_STATE_INITIALIZING = 2, PINOS_NODE_STATE_IDLE = 2,
PINOS_NODE_STATE_IDLE = 3, PINOS_NODE_STATE_RUNNING = 3,
PINOS_NODE_STATE_RUNNING = 4,
}; };
const char * pinos_node_state_as_string (PinosNodeState state); const char * pinos_node_state_as_string (PinosNodeState state);

View file

@ -55,7 +55,11 @@ id_map_get_uri (SpaIDMap *map, uint32_t id)
IDMap *this = SPA_CONTAINER_OF (map, IDMap, map); IDMap *this = SPA_CONTAINER_OF (map, IDMap, map);
if (id == SPA_ID_INVALID) if (id == SPA_ID_INVALID)
return NULL; 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 = { static IDMap default_id_map = {

View file

@ -844,8 +844,6 @@ pinos_stream_connect (PinosStream *stream,
{ {
PinosStreamImpl *impl = SPA_CONTAINER_OF (stream, PinosStreamImpl, this); PinosStreamImpl *impl = SPA_CONTAINER_OF (stream, PinosStreamImpl, this);
PinosMessageCreateClientNode ccn; PinosMessageCreateClientNode ccn;
SpaDict dict;
SpaDictItem items[1];
impl->direction = direction == PINOS_DIRECTION_INPUT ? SPA_DIRECTION_INPUT : SPA_DIRECTION_OUTPUT; impl->direction = direction == PINOS_DIRECTION_INPUT ? SPA_DIRECTION_INPUT : SPA_DIRECTION_OUTPUT;
impl->port_id = 0; impl->port_id = 0;
@ -866,7 +864,7 @@ pinos_stream_connect (PinosStream *stream,
impl->node_proxy = pinos_proxy_new (stream->context, impl->node_proxy = pinos_proxy_new (stream->context,
SPA_ID_INVALID, SPA_ID_INVALID,
0); stream->context->uri.client_node);
pinos_proxy_set_dispatch (impl->node_proxy, pinos_proxy_set_dispatch (impl->node_proxy,
stream_dispatch_func, stream_dispatch_func,
@ -874,11 +872,7 @@ pinos_stream_connect (PinosStream *stream,
ccn.seq = ++impl->seq; ccn.seq = ++impl->seq;
ccn.name = "client-node"; ccn.name = "client-node";
dict.n_items = 1; ccn.props = &stream->properties->dict;
dict.items = items;
items[0].key = "pinos.target.node";
items[0].value = port_path;
ccn.props = &dict;
ccn.new_id = impl->node_proxy->id; ccn.new_id = impl->node_proxy->id;
pinos_proxy_send_message (stream->context->core_proxy, pinos_proxy_send_message (stream->context->core_proxy,

View file

@ -42,8 +42,16 @@ check_global_owner (PinosCore *core,
PinosGlobal *global; PinosGlobal *global;
global = pinos_map_lookup (&core->objects, id); 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 static void

View file

@ -82,7 +82,8 @@ try_link_port (PinosNode *node, PinosPort *port, ModuleImpl *impl)
error: 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; return;
} }
} }
@ -271,6 +272,6 @@ module_destroy (ModuleImpl *impl)
bool bool
pinos__module_init (PinosModule * module, const char * args) pinos__module_init (PinosModule * module, const char * args)
{ {
module_new (module->core, NULL); module->user_data = module_new (module->core, NULL);
return true; return true;
} }

View file

@ -251,7 +251,7 @@ client_new (PinosProtocolDBus *impl,
PinosProtocolDBusClient *this; PinosProtocolDBusClient *this;
PinosClient *client; PinosClient *client;
client = pinos_client_new (impl->core, NULL); client = pinos_client_new (impl->core, NULL, NULL);
if ((this = (PinosProtocolDBusClient *) find_object (impl, client))) { if ((this = (PinosProtocolDBusClient *) find_object (impl, client))) {
pinos_client1_set_sender (this->parent.iface, sender); pinos_client1_set_sender (this->parent.iface, sender);

View file

@ -180,6 +180,7 @@ client_new (PinosProtocolNative *impl,
PinosProtocolNativeClient *this; PinosProtocolNativeClient *this;
PinosClient *client; PinosClient *client;
socklen_t len; socklen_t len;
struct ucred ucred, *ucredp;
this = calloc (1, sizeof (PinosProtocolNativeClient)); this = calloc (1, sizeof (PinosProtocolNativeClient));
if (this == NULL) if (this == NULL)
@ -200,7 +201,15 @@ client_new (PinosProtocolNative *impl,
if (this->connection == NULL) if (this->connection == NULL)
goto no_connection; 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) if (client == NULL)
goto no_client; goto no_client;
@ -210,14 +219,6 @@ client_new (PinosProtocolNative *impl,
client_send_func, client_send_func,
this); 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); spa_list_insert (impl->client_list.prev, &this->link);
pinos_global_bind (impl->core->global, pinos_global_bind (impl->core->global,

View file

@ -113,6 +113,7 @@ pinos__module_init (PinosModule * module, const char * args)
} }
} }
free (argv); free (argv);
pinos_free_strv (tmp_argv);
} }
pinos_spa_monitor_load (module->core, "build/spa/plugins/alsa/libspa-alsa.so", "alsa-monitor"); pinos_spa_monitor_load (module->core, "build/spa/plugins/alsa/libspa-alsa.so", "alsa-monitor");

View file

@ -119,6 +119,7 @@ typedef struct
SpaProxy proxy; SpaProxy proxy;
PinosListener node_free;
PinosListener transport_changed; PinosListener transport_changed;
PinosListener loop_changed; PinosListener loop_changed;
PinosListener global_added; PinosListener global_added;
@ -177,6 +178,9 @@ spa_proxy_node_send_command (SpaNode *node,
this = SPA_CONTAINER_OF (node, SpaProxy, node); this = SPA_CONTAINER_OF (node, SpaProxy, node);
if (this->resource == NULL)
return SPA_RESULT_OK;
switch (command->type) { switch (command->type) {
case SPA_NODE_COMMAND_INVALID: case SPA_NODE_COMMAND_INVALID:
return SPA_RESULT_INVALID_COMMAND; return SPA_RESULT_INVALID_COMMAND;
@ -200,7 +204,6 @@ spa_proxy_node_send_command (SpaNode *node,
uint8_t cmd = PINOS_TRANSPORT_CMD_NEED_DATA; uint8_t cmd = PINOS_TRANSPORT_CMD_NEED_DATA;
write (this->data_source.fd, &cmd, 1); write (this->data_source.fd, &cmd, 1);
} }
res = SPA_RESULT_RETURN_ASYNC (cnc.seq); res = SPA_RESULT_RETURN_ASYNC (cnc.seq);
break; break;
} }
@ -295,7 +298,7 @@ spa_proxy_node_get_port_ids (SpaNode *node,
} }
static void static void
do_update_port (SpaProxy *this, do_update_port (SpaProxy *this,
PinosMessagePortUpdate *pu) PinosMessagePortUpdate *pu)
{ {
SpaProxyPort *port; SpaProxyPort *port;
@ -312,17 +315,22 @@ do_update_port (SpaProxy *this,
for (i = 0; i < port->n_formats; i++) for (i = 0; i < port->n_formats; i++)
free (port->formats[i]); free (port->formats[i]);
port->n_formats = pu->n_possible_formats; 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++) { for (i = 0; i < port->n_formats; i++) {
size = pinos_serialize_format_get_size (pu->possible_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 (pu->change_mask & PINOS_MESSAGE_PORT_UPDATE_FORMAT) {
if (port->format) if (port->format)
free (port->format); free (port->format);
size = pinos_serialize_format_get_size (pu->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) { if (pu->change_mask & PINOS_MESSAGE_PORT_UPDATE_PROPS) {
@ -332,7 +340,7 @@ do_update_port (SpaProxy *this,
if (port->info) if (port->info)
free (port->info); free (port->info);
size = pinos_serialize_port_info_get_size (pu->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) { if (!port->valid) {
@ -482,6 +490,9 @@ spa_proxy_node_port_set_format (SpaNode *node,
if (!CHECK_PORT (this, direction, port_id)) if (!CHECK_PORT (this, direction, port_id))
return SPA_RESULT_INVALID_PORT; return SPA_RESULT_INVALID_PORT;
if (this->resource == NULL)
return SPA_RESULT_OK;
sf.seq = this->seq++; sf.seq = this->seq++;
sf.direction = direction; sf.direction = direction;
sf.port_id = port_id; sf.port_id = port_id;
@ -641,6 +652,11 @@ spa_proxy_node_port_use_buffers (SpaNode *node,
mb = NULL; mb = NULL;
} }
port->n_buffers = n_buffers;
if (this->resource == NULL)
return SPA_RESULT_OK;
n_mem = 0; n_mem = 0;
for (i = 0; i < n_buffers; i++) { for (i = 0; i < n_buffers; i++) {
ProxyBuffer *b = &port->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.seq = this->seq++;
ub.direction = direction; ub.direction = direction;
ub.port_id = port_id; ub.port_id = port_id;
@ -1169,6 +1183,9 @@ on_transport_changed (PinosListener *listener,
PinosTransportInfo info; PinosTransportInfo info;
PinosMessageTransportUpdate tu; PinosMessageTransportUpdate tu;
if (this->resource == NULL)
return;
pinos_transport_get_info (node->transport, &info); pinos_transport_get_info (node->transport, &info);
tu.memfd = info.memfd; tu.memfd = info.memfd;
@ -1194,6 +1211,7 @@ on_global_added (PinosListener *listener,
PinosGlobal *global) PinosGlobal *global)
{ {
PinosClientNodeImpl *impl = SPA_CONTAINER_OF (listener, PinosClientNodeImpl, global_added); PinosClientNodeImpl *impl = SPA_CONTAINER_OF (listener, PinosClientNodeImpl, global_added);
if (global->object == impl->this.node) if (global->object == impl->this.node)
global->owner = impl->this.client; global->owner = impl->this.client;
} }
@ -1222,7 +1240,25 @@ proxy_clear (SpaProxy *this)
static void static void
client_node_resource_destroy (PinosResource *resource) 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; return NULL;
this = &impl->this; this = &impl->this;
this->client = client;
impl->core = client->core; impl->core = client->core;
impl->data_fd = -1; impl->data_fd = -1;
pinos_log_debug ("client-node %p: new", impl); pinos_log_debug ("client-node %p: new", impl);
@ -1277,6 +1315,10 @@ pinos_client_node_new (PinosClient *client,
impl->proxy.resource = this->resource; 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, pinos_signal_add (&this->node->transport_changed,
&impl->transport_changed, &impl->transport_changed,
on_transport_changed); on_transport_changed);
@ -1303,24 +1345,6 @@ error_no_node:
return NULL; 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 void
pinos_client_node_destroy (PinosClientNode * this) 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_emit (&this->destroy_signal, this);
pinos_signal_remove (&impl->global_added); pinos_signal_remove (&impl->global_added);
pinos_signal_remove (&impl->loop_changed);
pinos_signal_remove (&impl->transport_changed);
pinos_node_destroy (this->node); pinos_node_destroy (this->node);
pinos_main_loop_defer (this->node->core->main_loop,
this,
SPA_RESULT_WAIT_SYNC,
(PinosDeferFunc) on_node_remove,
this);
} }
/** /**

View file

@ -110,6 +110,7 @@ no_mem:
*/ */
PinosClient * PinosClient *
pinos_client_new (PinosCore *core, pinos_client_new (PinosCore *core,
struct ucred *ucred,
PinosProperties *properties) PinosProperties *properties)
{ {
PinosClient *this; PinosClient *this;
@ -123,6 +124,8 @@ pinos_client_new (PinosCore *core,
this = &impl->this; this = &impl->this;
this->core = core; this->core = core;
if ((this->ucred_valid = (ucred != NULL)))
this->ucred = *ucred;
this->properties = properties; this->properties = properties;
spa_list_init (&this->resource_list); spa_list_init (&this->resource_list);
@ -142,23 +145,6 @@ pinos_client_new (PinosCore *core,
return this; 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 static void
destroy_resource (void *object, destroy_resource (void *object,
void *data) void *data)
@ -176,23 +162,26 @@ void
pinos_client_destroy (PinosClient * client) pinos_client_destroy (PinosClient * client)
{ {
PinosResource *resource, *tmp; PinosResource *resource, *tmp;
PinosClientImpl *impl = SPA_CONTAINER_OF (client, PinosClientImpl, this);
pinos_log_debug ("client %p: destroy", client); pinos_log_debug ("client %p: destroy", client);
pinos_signal_emit (&client->destroy_signal, 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); spa_list_remove (&client->link);
pinos_global_destroy (client->global);
spa_list_for_each_safe (resource, tmp, &client->resource_list, link) spa_list_for_each_safe (resource, tmp, &client->resource_list, link)
pinos_resource_destroy (resource); pinos_resource_destroy (resource);
pinos_main_loop_defer (client->core->main_loop, pinos_map_for_each (&client->objects, destroy_resource, client);
client,
SPA_RESULT_WAIT_SYNC, pinos_log_debug ("client %p: free", impl);
sync_destroy, pinos_map_clear (&client->objects);
client);
if (client->properties)
pinos_properties_free (client->properties);
free (impl);
} }
void void

View file

@ -62,10 +62,11 @@ struct _PinosClient {
SpaList resource_list; SpaList resource_list;
PINOS_SIGNAL (destroy_signal, (PinosListener *listener, PINOS_SIGNAL (destroy_signal, (PinosListener *listener,
PinosClient *client)); PinosClient *client));
}; };
PinosClient * pinos_client_new (PinosCore *core, PinosClient * pinos_client_new (PinosCore *core,
struct ucred *ucred,
PinosProperties *properties); PinosProperties *properties);
void pinos_client_destroy (PinosClient *client); void pinos_client_destroy (PinosClient *client);

View file

@ -192,6 +192,13 @@ no_mem:
return SPA_RESULT_NO_MEMORY; return SPA_RESULT_NO_MEMORY;
} }
static void
core_unbind_func (void *data)
{
PinosResource *resource = data;
resource->client->core_resource = NULL;
}
static SpaResult static SpaResult
core_bind_func (PinosGlobal *global, core_bind_func (PinosGlobal *global,
PinosClient *client, PinosClient *client,
@ -207,7 +214,7 @@ core_bind_func (PinosGlobal *global,
id, id,
global->type, global->type,
global->object, global->object,
NULL); core_unbind_func);
if (resource == NULL) if (resource == NULL)
goto no_mem; goto no_mem;
@ -310,10 +317,14 @@ pinos_core_destroy (PinosCore *core)
{ {
PinosCoreImpl *impl = SPA_CONTAINER_OF (core, PinosCoreImpl, this); PinosCoreImpl *impl = SPA_CONTAINER_OF (core, PinosCoreImpl, this);
pinos_log_debug ("core %p: destroy", core);
pinos_signal_emit (&core->destroy_signal, core); pinos_signal_emit (&core->destroy_signal, core);
pinos_data_loop_destroy (core->data_loop); pinos_data_loop_destroy (core->data_loop);
pinos_map_clear (&core->objects);
pinos_log_debug ("core %p: free", core);
free (impl); free (impl);
} }
@ -350,10 +361,11 @@ pinos_core_add_global (PinosCore *core,
spa_list_insert (core->global_list.prev, &this->link); spa_list_insert (core->global_list.prev, &this->link);
pinos_signal_emit (&core->global_added, core, this); pinos_signal_emit (&core->global_added, core, this);
pinos_log_debug ("global %p: new %u", this, this->id);
ng.id = this->id; ng.id = this->id;
ng.type = spa_id_map_get_uri (core->uri.map, this->type); 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) { spa_list_for_each (registry, &core->registry_resource_list, link) {
pinos_resource_send_message (registry, pinos_resource_send_message (registry,
PINOS_MESSAGE_NOTIFY_GLOBAL, PINOS_MESSAGE_NOTIFY_GLOBAL,
@ -384,18 +396,6 @@ pinos_global_bind (PinosGlobal *global,
return res; 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 void
pinos_global_destroy (PinosGlobal *global) 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_log_debug ("global %p: destroy %u", global, global->id);
pinos_signal_emit (&global->destroy_signal, global); 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; ng.id = global->id;
spa_list_for_each (registry, &core->registry_resource_list, link) { spa_list_for_each (registry, &core->registry_resource_list, link) {
pinos_resource_send_message (registry, pinos_resource_send_message (registry,
@ -419,11 +414,13 @@ pinos_global_destroy (PinosGlobal *global)
true); true);
} }
pinos_main_loop_defer (core->main_loop, pinos_map_remove (&core->objects, global->id);
global,
SPA_RESULT_WAIT_SYNC, spa_list_remove (&global->link);
sync_destroy, pinos_signal_emit (&core->global_removed, core, global);
global);
pinos_log_debug ("global %p: free", global);
free (global);
} }
PinosPort * PinosPort *

View file

@ -32,6 +32,8 @@ typedef struct
{ {
PinosLink this; PinosLink this;
int refcount;
uint32_t seq; uint32_t seq;
SpaFormat **format_filter; 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); 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 static void
on_port_destroy (PinosLink *this, on_port_destroy (PinosLink *this,
PinosPort *port) PinosPort *port)
{ {
PinosLinkImpl *impl = (PinosLinkImpl *) this; PinosLinkImpl *impl = (PinosLinkImpl *) this;
PinosPort *other; PinosPort *other;
SpaResult res = SPA_RESULT_OK;
if (port == this->input) { if (port == this->input) {
pinos_log_debug ("link %p: input port destroyed %p", this, port); 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_port_clear_buffers (other);
} }
pinos_main_loop_defer (this->core->main_loop, pinos_signal_emit (&this->core->port_unlinked, this, port);
port,
res, pinos_link_update_state (this, PINOS_LINK_STATE_UNLINKED, NULL);
(PinosDeferFunc) on_port_unlinked, pinos_link_destroy (this);
this);
} }
static void static void
@ -749,11 +737,31 @@ link_dispatch_func (void *object,
return SPA_RESULT_OK; 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 static void
link_unbind_func (void *data) link_unbind_func (void *data)
{ {
PinosResource *resource = data; PinosResource *resource = data;
PinosLink *this = resource->object;
PinosLinkImpl *impl = SPA_CONTAINER_OF (this, PinosLinkImpl, this);
spa_list_remove (&resource->link); spa_list_remove (&resource->link);
if (--impl->refcount == 0)
pinos_link_free (this);
} }
static SpaResult static SpaResult
@ -763,6 +771,7 @@ link_bind_func (PinosGlobal *global,
uint32_t id) uint32_t id)
{ {
PinosLink *this = global->object; PinosLink *this = global->object;
PinosLinkImpl *impl = SPA_CONTAINER_OF (this, PinosLinkImpl, this);
PinosResource *resource; PinosResource *resource;
PinosMessageLinkInfo m; PinosMessageLinkInfo m;
PinosLinkInfo info; PinosLinkInfo info;
@ -775,6 +784,8 @@ link_bind_func (PinosGlobal *global,
if (resource == NULL) if (resource == NULL)
goto no_mem; goto no_mem;
impl->refcount++;
pinos_resource_set_dispatch (resource, pinos_resource_set_dispatch (resource,
link_dispatch_func, link_dispatch_func,
global); global);
@ -790,6 +801,7 @@ link_bind_func (PinosGlobal *global,
info.output_port_id = this->output ? this->output->port_id : -1; 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_node_id = this->input ? this->input->node->global->id : -1;
info.input_port_id = this->input ? this->input->port_id : -1; info.input_port_id = this->input ? this->input->port_id : -1;
return pinos_resource_send_message (resource, return pinos_resource_send_message (resource,
PINOS_MESSAGE_LINK_INFO, PINOS_MESSAGE_LINK_INFO,
&m, &m,
@ -821,12 +833,14 @@ pinos_link_new (PinosCore *core,
this->core = core; this->core = core;
this->properties = properties; this->properties = properties;
this->state = PINOS_LINK_STATE_INIT; this->state = PINOS_LINK_STATE_INIT;
impl->refcount = 1;
this->input = input; this->input = input;
this->output = output; this->output = output;
spa_list_init (&this->resource_list); spa_list_init (&this->resource_list);
pinos_signal_init (&this->destroy_signal); pinos_signal_init (&this->destroy_signal);
pinos_signal_init (&this->free_signal);
impl->format_filter = format_filter; impl->format_filter = format_filter;
@ -884,6 +898,7 @@ do_link_remove_done (SpaLoop *loop,
void *user_data) void *user_data)
{ {
PinosLink *this = user_data; PinosLink *this = user_data;
PinosLinkImpl *impl = SPA_CONTAINER_OF (this, PinosLinkImpl, this);
if (this->input) { if (this->input) {
spa_list_remove (&this->input_link); spa_list_remove (&this->input_link);
@ -907,11 +922,8 @@ do_link_remove_done (SpaLoop *loop,
clear_port_buffers (this, this->output); clear_port_buffers (this, this->output);
this->output = NULL; this->output = NULL;
} }
if (--impl->refcount == 0)
pinos_main_loop_defer_complete (this->core->main_loop, pinos_link_free (this);
this,
seq,
SPA_RESULT_OK);
return SPA_RESULT_OK; return SPA_RESULT_OK;
} }
@ -945,22 +957,6 @@ do_link_remove (SpaLoop *loop,
return res; 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: * pinos_link_destroy:
* @link: a #PinosLink * @link: a #PinosLink
@ -970,7 +966,6 @@ sync_destroy (void *object,
void void
pinos_link_destroy (PinosLink * this) pinos_link_destroy (PinosLink * this)
{ {
SpaResult res = SPA_RESULT_OK;
PinosLinkImpl *impl = SPA_CONTAINER_OF (this, PinosLinkImpl, this); PinosLinkImpl *impl = SPA_CONTAINER_OF (this, PinosLinkImpl, this);
PinosResource *resource, *tmp; PinosResource *resource, *tmp;
@ -987,31 +982,26 @@ pinos_link_destroy (PinosLink * this)
pinos_signal_remove (&impl->input_port_destroy); pinos_signal_remove (&impl->input_port_destroy);
pinos_signal_remove (&impl->input_async_complete); pinos_signal_remove (&impl->input_async_complete);
res = pinos_loop_invoke (this->input->node->data_loop->loop, impl->refcount++;
do_link_remove, pinos_loop_invoke (this->input->node->data_loop->loop,
impl->seq++, do_link_remove,
0, impl->seq++,
NULL, 0,
this); NULL,
this);
pinos_main_loop_defer (this->core->main_loop, this, res, NULL, NULL);
} }
if (this->output) { if (this->output) {
pinos_signal_remove (&impl->output_port_destroy); pinos_signal_remove (&impl->output_port_destroy);
pinos_signal_remove (&impl->output_async_complete); pinos_signal_remove (&impl->output_async_complete);
res = pinos_loop_invoke (this->output->node->data_loop->loop, impl->refcount++;
do_link_remove, pinos_loop_invoke (this->output->node->data_loop->loop,
impl->seq++, do_link_remove,
0, impl->seq++,
NULL, 0,
this); NULL,
pinos_main_loop_defer (this->core->main_loop, this, res, NULL, NULL); this);
} }
if (--impl->refcount == 0)
pinos_main_loop_defer (this->core->main_loop, pinos_link_free (this);
this,
SPA_RESULT_WAIT_SYNC,
sync_destroy,
this);
} }

View file

@ -51,6 +51,8 @@ struct _PinosLink {
PINOS_SIGNAL (destroy_signal, (PinosListener *, PINOS_SIGNAL (destroy_signal, (PinosListener *,
PinosLink *)); PinosLink *));
PINOS_SIGNAL (free_signal, (PinosListener *,
PinosLink *));
SpaList resource_list; SpaList resource_list;

View file

@ -30,14 +30,16 @@ extern "C" {
typedef struct _PinosModule PinosModule; typedef struct _PinosModule PinosModule;
struct _PinosModule { struct _PinosModule {
PinosCore *core; PinosCore *core;
SpaList link; SpaList link;
PinosGlobal *global; PinosGlobal *global;
char *name; char *name;
char *filename; char *filename;
char *args; char *args;
void *user_data;
PINOS_SIGNAL (destroy_signal, (PinosListener *listener, PINOS_SIGNAL (destroy_signal, (PinosListener *listener,
PinosModule *module)); PinosModule *module));
}; };

View file

@ -461,10 +461,9 @@ init_complete (PinosNode *this)
pinos_log_debug ("node %p: init completed", this); pinos_log_debug ("node %p: init completed", this);
impl->async_init = false; impl->async_init = false;
spa_list_insert (this->core->node_list.prev, &this->link);
pinos_node_update_state (this, PINOS_NODE_STATE_SUSPENDED, NULL); 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, this->global = pinos_core_add_global (this->core,
NULL, NULL,
this->core->uri.node, this->core->uri.node,
@ -512,6 +511,7 @@ pinos_node_new (PinosCore *core,
pinos_log_warn ("node %p: error setting callback", this); pinos_log_warn ("node %p: error setting callback", this);
pinos_signal_init (&this->destroy_signal); pinos_signal_init (&this->destroy_signal);
pinos_signal_init (&this->free_signal);
pinos_signal_init (&this->async_complete); pinos_signal_init (&this->async_complete);
pinos_signal_init (&this->transport_changed); pinos_signal_init (&this->transport_changed);
pinos_signal_init (&this->loop_changed); pinos_signal_init (&this->loop_changed);
@ -564,6 +564,7 @@ do_node_remove_done (SpaLoop *loop,
void *user_data) void *user_data)
{ {
PinosNode *this = user_data; PinosNode *this = user_data;
PinosNodeImpl *impl = SPA_CONTAINER_OF (this, PinosNodeImpl, this);
PinosPort *port, *tmp; PinosPort *port, *tmp;
pinos_log_debug ("node %p: remove done, destroy ports", this); 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) spa_list_for_each_safe (port, tmp, &this->output_ports, link)
pinos_port_destroy (port); pinos_port_destroy (port);
pinos_main_loop_defer_complete (this->core->main_loop, pinos_log_debug ("node %p: free", this);
this, pinos_signal_emit (&this->free_signal, this);
seq,
SPA_RESULT_OK); 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; return SPA_RESULT_OK;
} }
@ -620,24 +632,6 @@ do_node_remove (SpaLoop *loop,
return res; 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: * pinos_node_destroy:
* @node: a #PinosNode * @node: a #PinosNode
@ -648,7 +642,6 @@ sync_destroy (void *object,
void void
pinos_node_destroy (PinosNode * this) pinos_node_destroy (PinosNode * this)
{ {
SpaResult res;
PinosNodeImpl *impl = SPA_CONTAINER_OF (this, PinosNodeImpl, this); PinosNodeImpl *impl = SPA_CONTAINER_OF (this, PinosNodeImpl, this);
PinosResource *resource, *tmp; PinosResource *resource, *tmp;
@ -661,24 +654,12 @@ pinos_node_destroy (PinosNode * this)
spa_list_for_each_safe (resource, tmp, &this->resource_list, link) spa_list_for_each_safe (resource, tmp, &this->resource_list, link)
pinos_resource_destroy (resource); pinos_resource_destroy (resource);
res = pinos_loop_invoke (this->data_loop->loop, pinos_loop_invoke (this->data_loop->loop,
do_node_remove, do_node_remove,
impl->seq++, impl->seq++,
0, 0,
NULL, NULL,
this); 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);
} }
/** /**
@ -771,9 +752,6 @@ pinos_node_set_state (PinosNode *node,
res = suspend_node (node); res = suspend_node (node);
break; break;
case PINOS_NODE_STATE_INITIALIZING:
break;
case PINOS_NODE_STATE_IDLE: case PINOS_NODE_STATE_IDLE:
res = pause_node (node); res = pause_node (node);
break; break;

View file

@ -79,6 +79,8 @@ struct _PinosNode {
PINOS_SIGNAL (destroy_signal, (PinosListener *listener, PINOS_SIGNAL (destroy_signal, (PinosListener *listener,
PinosNode *object)); PinosNode *object));
PINOS_SIGNAL (free_signal, (PinosListener *listener,
PinosNode *object));
PINOS_SIGNAL (async_complete, (PinosListener *listener, PINOS_SIGNAL (async_complete, (PinosListener *listener,
PinosNode *node, PinosNode *node,

View file

@ -56,17 +56,6 @@ pinos_port_new (PinosNode *node,
return this; return this;
} }
static void
sync_destroy (void *object,
void *data,
SpaResult res,
uint32_t id)
{
PinosPort *port = object;
free (port);
}
void void
pinos_port_destroy (PinosPort *port) pinos_port_destroy (PinosPort *port)
{ {
@ -83,11 +72,7 @@ pinos_port_destroy (PinosPort *port)
port->buffers = NULL; port->buffers = NULL;
port->n_buffers = 0; port->n_buffers = 0;
pinos_main_loop_defer (port->node->core->main_loop, free (port);
port,
SPA_RESULT_WAIT_SYNC,
sync_destroy,
port);
} }
static SpaResult static SpaResult

View file

@ -59,28 +59,12 @@ pinos_resource_new (PinosClient *client,
return this; return this;
} }
static void 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
pinos_resource_destroy (PinosResource *resource) pinos_resource_destroy (PinosResource *resource)
{ {
pinos_log_debug ("resource %p: destroy", resource); pinos_log_debug ("resource %p: destroy", resource);
pinos_signal_emit (&resource->destroy_signal, 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) { if (resource->client->core_resource) {
PinosMessageRemoveId m; PinosMessageRemoveId m;
m.id = resource->id; m.id = resource->id;
@ -90,13 +74,13 @@ pinos_resource_destroy (PinosResource *resource)
true); true);
} }
pinos_main_loop_defer (resource->core->main_loop, pinos_map_remove (&resource->client->objects, resource->id);
resource,
SPA_RESULT_WAIT_SYNC,
sync_destroy,
resource);
return SPA_RESULT_OK; if (resource->destroy)
resource->destroy (resource);
pinos_log_debug ("resource %p: free", resource);
free (resource);
} }
void void

View file

@ -62,7 +62,7 @@ PinosResource * pinos_resource_new (PinosClient *client,
uint32_t type, uint32_t type,
void *object, void *object,
PinosDestroy destroy); PinosDestroy destroy);
SpaResult pinos_resource_destroy (PinosResource *resource); void pinos_resource_destroy (PinosResource *resource);
void pinos_resource_set_dispatch (PinosResource *resource, void pinos_resource_set_dispatch (PinosResource *resource,
PinosDispatchFunc func, PinosDispatchFunc func,