From d71cf2418305c07dc3bd9b5740d7e0a3c5099825 Mon Sep 17 00:00:00 2001 From: Pauli Virtanen Date: Tue, 22 Feb 2022 22:18:20 +0200 Subject: [PATCH] global: update generation number also in clients without registry Not all clients have an existing registry, and the registry generation number will not be updated for them. However, we would like to check for stale globals also elsewhere, eg. metadata, and it must work also in this case. To avoid failing to update client registry generation, on global addition which the client would see if it had a registry, send done message for the new global id instead. --- .../module-protocol-native/protocol-footer.c | 12 ++++++---- .../module-protocol-native/protocol-footer.h | 1 - src/pipewire/global.c | 24 +++++++++++++++++-- src/pipewire/private.h | 1 + 4 files changed, 30 insertions(+), 8 deletions(-) diff --git a/src/modules/module-protocol-native/protocol-footer.c b/src/modules/module-protocol-native/protocol-footer.c index f3c108505..bc4caa4a8 100644 --- a/src/modules/module-protocol-native/protocol-footer.c +++ b/src/modules/module-protocol-native/protocol-footer.c @@ -95,8 +95,8 @@ void marshal_client_footers(struct footer_client_global_state *state, struct pw_ { struct footer_builder fb = FOOTER_BUILDER_INIT(builder); - if (client->context->generation != state->last_sent_generation) { - state->last_sent_generation = client->context->generation; + if (client->context->generation != client->sent_generation) { + client->sent_generation = client->context->generation; pw_log_trace("impl-client %p: send server registry generation:%"PRIu64, client, client->context->generation); @@ -117,10 +117,11 @@ int demarshal_core_generation(void *object, struct spa_pod_parser *parser) if (spa_pod_parser_get_long(parser, &generation) < 0) return -EINVAL; - core->recv_generation = (uint64_t)generation; + core->recv_generation = SPA_MAX(core->recv_generation, + (uint64_t)generation); pw_log_trace("core %p: recv server registry generation:%"PRIu64, - core->core, generation); + core, generation); return 0; } @@ -133,7 +134,8 @@ int demarshal_client_generation(void *object, struct spa_pod_parser *parser) if (spa_pod_parser_get_long(parser, &generation) < 0) return -EINVAL; - client->recv_generation = (uint64_t)generation; + client->recv_generation = SPA_MAX(client->recv_generation, + (uint64_t)generation); pw_log_trace("impl-client %p: recv client registry generation:%"PRIu64, client, generation); diff --git a/src/modules/module-protocol-native/protocol-footer.h b/src/modules/module-protocol-native/protocol-footer.h index a097fd0a8..bdbec0430 100644 --- a/src/modules/module-protocol-native/protocol-footer.h +++ b/src/modules/module-protocol-native/protocol-footer.h @@ -44,7 +44,6 @@ struct footer_core_global_state { }; struct footer_client_global_state { - uint64_t last_sent_generation; }; struct footer_demarshal { diff --git a/src/pipewire/global.c b/src/pipewire/global.c index e67053073..aa2a048ce 100644 --- a/src/pipewire/global.c +++ b/src/pipewire/global.c @@ -139,6 +139,7 @@ int pw_global_register(struct pw_global *global) { struct pw_resource *registry; struct pw_context *context = global->context; + struct pw_impl_client *client; if (global->registered) return -EEXIST; @@ -150,8 +151,8 @@ int pw_global_register(struct pw_global *global) spa_list_for_each(registry, &context->registry_resource_list, link) { uint32_t permissions = pw_global_get_permissions(global, registry->client); - pw_log_debug("registry %p: global %d %08x serial:%"PRIu64, - registry, global->id, permissions, global->serial); + pw_log_debug("registry %p: global %d %08x serial:%"PRIu64" generation:%"PRIu64, + registry, global->id, permissions, global->serial, global->generation); if (PW_PERM_IS_R(permissions)) pw_registry_resource_global(registry, global->id, @@ -161,6 +162,25 @@ int pw_global_register(struct pw_global *global) &global->properties->dict); } + /* Ensure a message is sent also to clients without registries, to force + * generation number update. */ + spa_list_for_each(client, &context->client_list, link) { + uint32_t permissions; + + if (client->sent_generation >= context->generation) + continue; + if (!client->core_resource) + continue; + + permissions = pw_global_get_permissions(global, client); + if (PW_PERM_IS_R(permissions)) { + pw_log_debug("impl-client %p: (no registry) global %d %08x serial:%"PRIu64 + " generation:%"PRIu64, client, global->id, permissions, global->serial, + global->generation); + pw_core_resource_done(client->core_resource, global->id, 0); + } + } + pw_log_debug("%p: registered %u", global, global->id); pw_context_emit_global_added(context, global); diff --git a/src/pipewire/private.h b/src/pipewire/private.h index ea166dac0..b5ae51ab8 100644 --- a/src/pipewire/private.h +++ b/src/pipewire/private.h @@ -300,6 +300,7 @@ struct pw_impl_client { int recv_seq; /**< last received sequence number */ int send_seq; /**< last sender sequence number */ uint64_t recv_generation; /**< last received registry generation */ + uint64_t sent_generation; /**< last sent registry generation */ void *user_data; /**< extra user data */