mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	gst: keep track of node ports
Keep a list of ports for the node. When the node goes away, clear the port links to the node. Handle the case where the port no longer has a node. This avoids a crash when, for example, the node permission is removed and the port points to the now freed node_data. Fixes #3708
This commit is contained in:
		
							parent
							
								
									705c977e9e
								
							
						
					
					
						commit
						67fde171a2
					
				
					 1 changed files with 17 additions and 0 deletions
				
			
		| 
						 | 
					@ -180,9 +180,11 @@ struct node_data {
 | 
				
			||||||
  struct pw_node_info *info;
 | 
					  struct pw_node_info *info;
 | 
				
			||||||
  GstCaps *caps;
 | 
					  GstCaps *caps;
 | 
				
			||||||
  GstDevice *dev;
 | 
					  GstDevice *dev;
 | 
				
			||||||
 | 
					  struct spa_list ports;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct port_data {
 | 
					struct port_data {
 | 
				
			||||||
 | 
					  struct spa_list link;
 | 
				
			||||||
  struct node_data *node_data;
 | 
					  struct node_data *node_data;
 | 
				
			||||||
  struct pw_port *proxy;
 | 
					  struct pw_port *proxy;
 | 
				
			||||||
  struct spa_hook proxy_listener;
 | 
					  struct spa_hook proxy_listener;
 | 
				
			||||||
| 
						 | 
					@ -353,6 +355,9 @@ static void port_event_info(void *data, const struct pw_port_info *info)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  pw_log_debug("%p", port_data);
 | 
					  pw_log_debug("%p", port_data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (node_data == NULL)
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (info->change_mask & PW_PORT_CHANGE_MASK_PARAMS) {
 | 
					  if (info->change_mask & PW_PORT_CHANGE_MASK_PARAMS) {
 | 
				
			||||||
    for (i = 0; i < info->n_params; i++) {
 | 
					    for (i = 0; i < info->n_params; i++) {
 | 
				
			||||||
      uint32_t id = info->params[i].id;
 | 
					      uint32_t id = info->params[i].id;
 | 
				
			||||||
| 
						 | 
					@ -375,6 +380,9 @@ static void port_event_param(void *data, int seq, uint32_t id,
 | 
				
			||||||
  struct node_data *node_data = port_data->node_data;
 | 
					  struct node_data *node_data = port_data->node_data;
 | 
				
			||||||
  GstCaps *c1;
 | 
					  GstCaps *c1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (node_data == NULL)
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  c1 = gst_caps_from_format (param);
 | 
					  c1 = gst_caps_from_format (param);
 | 
				
			||||||
  if (c1 && node_data->caps)
 | 
					  if (c1 && node_data->caps)
 | 
				
			||||||
      gst_caps_append (node_data->caps, c1);
 | 
					      gst_caps_append (node_data->caps, c1);
 | 
				
			||||||
| 
						 | 
					@ -438,11 +446,17 @@ static void
 | 
				
			||||||
destroy_node (void *data)
 | 
					destroy_node (void *data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  struct node_data *nd = data;
 | 
					  struct node_data *nd = data;
 | 
				
			||||||
 | 
					  struct port_data *pd;
 | 
				
			||||||
  GstPipeWireDeviceProvider *self = nd->self;
 | 
					  GstPipeWireDeviceProvider *self = nd->self;
 | 
				
			||||||
  GstDeviceProvider *provider = GST_DEVICE_PROVIDER (self);
 | 
					  GstDeviceProvider *provider = GST_DEVICE_PROVIDER (self);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  pw_log_debug("destroy %p", nd);
 | 
					  pw_log_debug("destroy %p", nd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  spa_list_consume(pd, &nd->ports, link) {
 | 
				
			||||||
 | 
						  spa_list_remove(&pd->link);
 | 
				
			||||||
 | 
						  pd->node_data = NULL;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (nd->dev != NULL) {
 | 
					  if (nd->dev != NULL) {
 | 
				
			||||||
    gst_device_provider_device_remove (provider, GST_DEVICE (nd->dev));
 | 
					    gst_device_provider_device_remove (provider, GST_DEVICE (nd->dev));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					@ -472,6 +486,7 @@ destroy_port (void *data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  struct port_data *pd = data;
 | 
					  struct port_data *pd = data;
 | 
				
			||||||
  pw_log_debug("destroy %p", pd);
 | 
					  pw_log_debug("destroy %p", pd);
 | 
				
			||||||
 | 
					  spa_list_remove(&pd->link);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const struct pw_proxy_events proxy_port_events = {
 | 
					static const struct pw_proxy_events proxy_port_events = {
 | 
				
			||||||
| 
						 | 
					@ -515,6 +530,7 @@ static void registry_event_global(void *data, uint32_t id, uint32_t permissions,
 | 
				
			||||||
    nd->id = id;
 | 
					    nd->id = id;
 | 
				
			||||||
    if (!props || !spa_atou64(spa_dict_lookup(props, PW_KEY_OBJECT_SERIAL), &nd->serial, 0))
 | 
					    if (!props || !spa_atou64(spa_dict_lookup(props, PW_KEY_OBJECT_SERIAL), &nd->serial, 0))
 | 
				
			||||||
      nd->serial = SPA_ID_INVALID;
 | 
					      nd->serial = SPA_ID_INVALID;
 | 
				
			||||||
 | 
					    spa_list_init(&nd->ports);
 | 
				
			||||||
    spa_list_append(&self->nodes, &nd->link);
 | 
					    spa_list_append(&self->nodes, &nd->link);
 | 
				
			||||||
    pw_node_add_listener(node, &nd->node_listener, &node_events, nd);
 | 
					    pw_node_add_listener(node, &nd->node_listener, &node_events, nd);
 | 
				
			||||||
    pw_proxy_add_listener((struct pw_proxy*)node, &nd->proxy_listener, &proxy_node_events, nd);
 | 
					    pw_proxy_add_listener((struct pw_proxy*)node, &nd->proxy_listener, &proxy_node_events, nd);
 | 
				
			||||||
| 
						 | 
					@ -541,6 +557,7 @@ static void registry_event_global(void *data, uint32_t id, uint32_t permissions,
 | 
				
			||||||
    pd->id = id;
 | 
					    pd->id = id;
 | 
				
			||||||
    if (!props || !spa_atou64(spa_dict_lookup(props, PW_KEY_OBJECT_SERIAL), &pd->serial, 0))
 | 
					    if (!props || !spa_atou64(spa_dict_lookup(props, PW_KEY_OBJECT_SERIAL), &pd->serial, 0))
 | 
				
			||||||
      pd->serial = SPA_ID_INVALID;
 | 
					      pd->serial = SPA_ID_INVALID;
 | 
				
			||||||
 | 
					    spa_list_append(&nd->ports, &pd->link);
 | 
				
			||||||
    pw_port_add_listener(port, &pd->port_listener, &port_events, pd);
 | 
					    pw_port_add_listener(port, &pd->port_listener, &port_events, pd);
 | 
				
			||||||
    pw_proxy_add_listener((struct pw_proxy*)port, &pd->proxy_listener, &proxy_port_events, pd);
 | 
					    pw_proxy_add_listener((struct pw_proxy*)port, &pd->proxy_listener, &proxy_port_events, pd);
 | 
				
			||||||
    resync(self);
 | 
					    resync(self);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue