pw-mon: destroy proxies in global_remove event

Keep track of the proxies and remove them when the global is removed.
Otherwise we might end up in a case where the have 2 proxies when
an add/remove/add sequence of messages was queued.
This commit is contained in:
Wim Taymans 2021-11-03 17:25:11 +01:00
parent f70fdf5605
commit b0e3e43c42

View file

@ -57,6 +57,7 @@ struct data {
struct spa_hook registry_listener; struct spa_hook registry_listener;
struct spa_list pending_list; struct spa_list pending_list;
struct spa_list global_list;
}; };
struct proxy_data { struct proxy_data {
@ -72,6 +73,7 @@ struct proxy_data {
struct spa_hook proxy_listener; struct spa_hook proxy_listener;
struct spa_hook object_listener; struct spa_hook object_listener;
int pending_seq; int pending_seq;
struct spa_list global_link;
struct spa_list pending_link; struct spa_list pending_link;
print_func_t print_func; print_func_t print_func;
struct spa_list param_list; struct spa_list param_list;
@ -545,18 +547,19 @@ removed_proxy (void *data)
static void static void
destroy_proxy (void *data) destroy_proxy (void *data)
{ {
struct proxy_data *pd = data; struct proxy_data *pd = data;
spa_list_remove(&pd->global_link);
clear_params(pd); clear_params(pd);
remove_pending(pd); remove_pending(pd);
free(pd->type);
if (pd->info == NULL) if (pd->info == NULL)
return; return;
if (pd->destroy) if (pd->destroy)
pd->destroy(pd->info); pd->destroy(pd->info);
pd->info = NULL; pd->info = NULL;
free(pd->type);
} }
static const struct pw_proxy_events proxy_events = { static const struct pw_proxy_events proxy_events = {
@ -569,10 +572,10 @@ static void registry_event_global(void *data, uint32_t id,
uint32_t permissions, const char *type, uint32_t version, uint32_t permissions, const char *type, uint32_t version,
const struct spa_dict *props) const struct spa_dict *props)
{ {
struct data *d = data; struct data *d = data;
struct pw_proxy *proxy; struct pw_proxy *proxy;
uint32_t client_version; uint32_t client_version;
const void *events; const void *events;
struct proxy_data *pd; struct proxy_data *pd;
pw_destroy_t destroy; pw_destroy_t destroy;
print_func_t print_func = NULL; print_func_t print_func = NULL;
@ -618,11 +621,11 @@ static void registry_event_global(void *data, uint32_t id,
return; return;
} }
proxy = pw_registry_bind(d->registry, id, type, proxy = pw_registry_bind(d->registry, id, type,
client_version, client_version,
sizeof(struct proxy_data)); sizeof(struct proxy_data));
if (proxy == NULL) if (proxy == NULL)
goto no_mem; goto no_mem;
pd = pw_proxy_get_user_data(proxy); pd = pw_proxy_get_user_data(proxy);
pd->data = d; pd->data = d;
@ -636,19 +639,40 @@ static void registry_event_global(void *data, uint32_t id,
pd->pending_seq = 0; pd->pending_seq = 0;
pd->print_func = print_func; pd->print_func = print_func;
spa_list_init(&pd->param_list); spa_list_init(&pd->param_list);
pw_proxy_add_object_listener(proxy, &pd->object_listener, events, pd); pw_proxy_add_object_listener(proxy, &pd->object_listener, events, pd);
pw_proxy_add_listener(proxy, &pd->proxy_listener, &proxy_events, pd); pw_proxy_add_listener(proxy, &pd->proxy_listener, &proxy_events, pd);
return; spa_list_append(&d->global_list, &pd->global_link);
no_mem: return;
printf("failed to create proxy");
return; no_mem:
printf("failed to create proxy");
return;
}
static struct proxy_data *find_proxy(struct data *d, uint32_t id)
{
struct proxy_data *pd;
spa_list_for_each(pd, &d->global_list, global_link) {
if (pd->id == id)
return pd;
}
return NULL;
} }
static void registry_event_global_remove(void *object, uint32_t id) static void registry_event_global_remove(void *object, uint32_t id)
{ {
struct data *d = object;
struct proxy_data *pd;
printf("removed:\n"); printf("removed:\n");
printf("\tid: %u\n", id); printf("\tid: %u\n", id);
pd = find_proxy(d, id);
if (pd == NULL)
return;
if (pd->proxy)
pw_proxy_destroy(pd->proxy);
} }
static const struct pw_registry_events registry_events = { static const struct pw_registry_events registry_events = {
@ -744,6 +768,7 @@ int main(int argc, char *argv[])
} }
spa_list_init(&data.pending_list); spa_list_init(&data.pending_list);
spa_list_init(&data.global_list);
data.core = pw_context_connect(data.context, data.core = pw_context_connect(data.context,
pw_properties_new( pw_properties_new(