pulse-server: use cleanup event

Signal event to trigger cleanup from places where we are not allowed
to destroy objects, like from their signals.
This commit is contained in:
Wim Taymans 2020-11-13 19:33:12 +01:00
parent b447167339
commit b7b7c3817e

View file

@ -97,6 +97,7 @@ struct client {
const char *name; const char *name;
struct spa_source *source; struct spa_source *source;
struct spa_source *cleanup;
uint32_t version; uint32_t version;
@ -2233,6 +2234,7 @@ error:
struct pending_sample { struct pending_sample {
struct spa_list link; struct spa_list link;
struct client *client;
struct sample_play *play; struct sample_play *play;
struct spa_hook listener; struct spa_hook listener;
unsigned int done:1; unsigned int done:1;
@ -2248,7 +2250,10 @@ static void pending_sample_free(struct pending_sample *ps)
static void sample_play_done(void *data) static void sample_play_done(void *data)
{ {
struct pending_sample *ps = data; struct pending_sample *ps = data;
struct client *client = ps->client;
struct impl *impl = client->impl;
ps->done = true; ps->done = true;
pw_loop_signal_event(impl->loop, client->cleanup);
} }
static const struct sample_play_events sample_play_events = { static const struct sample_play_events sample_play_events = {
@ -2302,6 +2307,7 @@ static int do_play_sample(struct client *client, uint32_t command, uint32_t tag,
goto error_errno; goto error_errno;
ps = play->user_data; ps = play->user_data;
ps->client = client;
ps->play = play; ps->play = play;
sample_play_add_listener(play, &ps->listener, &sample_play_events, ps); sample_play_add_listener(play, &ps->listener, &sample_play_events, ps);
spa_list_append(&client->samples, &ps->link); spa_list_append(&client->samples, &ps->link);
@ -4410,6 +4416,8 @@ static void client_free(struct client *client)
pw_properties_free(client->props); pw_properties_free(client->props);
if (client->source) if (client->source)
pw_loop_destroy_source(impl->loop, client->source); pw_loop_destroy_source(impl->loop, client->source);
if (client->cleanup)
pw_loop_destroy_source(impl->loop, client->cleanup);
free(client); free(client);
} }
@ -4580,8 +4588,9 @@ exit:
return res; return res;
} }
static void client_clear_pending_samples(struct client *client) static void on_client_cleanup(void *data, uint64_t count)
{ {
struct client *client = data;
struct pending_sample *p, *t; struct pending_sample *p, *t;
spa_list_for_each_safe(p, t, &client->samples, link) { spa_list_for_each_safe(p, t, &client->samples, link) {
if (p->done) if (p->done)
@ -4625,7 +4634,6 @@ on_client_data(void *data, int fd, uint32_t mask)
} }
} }
} }
client_clear_pending_samples(client);
return; return;
error: error:
@ -4703,6 +4711,11 @@ on_connect(void *data, int fd, uint32_t mask)
if (client->source == NULL) if (client->source == NULL)
goto error; goto error;
client->cleanup = pw_loop_add_event(impl->loop,
on_client_cleanup, client);
if (client->cleanup == NULL)
goto error;
return; return;
error: error:
pw_log_error(NAME" %p: failed to create client: %m", impl); pw_log_error(NAME" %p: failed to create client: %m", impl);