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.
This commit is contained in:
Pauli Virtanen 2022-02-22 22:18:20 +02:00
parent a9accd1668
commit d71cf24183
4 changed files with 30 additions and 8 deletions

View file

@ -95,8 +95,8 @@ void marshal_client_footers(struct footer_client_global_state *state, struct pw_
{ {
struct footer_builder fb = FOOTER_BUILDER_INIT(builder); struct footer_builder fb = FOOTER_BUILDER_INIT(builder);
if (client->context->generation != state->last_sent_generation) { if (client->context->generation != client->sent_generation) {
state->last_sent_generation = client->context->generation; client->sent_generation = client->context->generation;
pw_log_trace("impl-client %p: send server registry generation:%"PRIu64, pw_log_trace("impl-client %p: send server registry generation:%"PRIu64,
client, client->context->generation); 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) if (spa_pod_parser_get_long(parser, &generation) < 0)
return -EINVAL; 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, pw_log_trace("core %p: recv server registry generation:%"PRIu64,
core->core, generation); core, generation);
return 0; 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) if (spa_pod_parser_get_long(parser, &generation) < 0)
return -EINVAL; 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, pw_log_trace("impl-client %p: recv client registry generation:%"PRIu64,
client, generation); client, generation);

View file

@ -44,7 +44,6 @@ struct footer_core_global_state {
}; };
struct footer_client_global_state { struct footer_client_global_state {
uint64_t last_sent_generation;
}; };
struct footer_demarshal { struct footer_demarshal {

View file

@ -139,6 +139,7 @@ int pw_global_register(struct pw_global *global)
{ {
struct pw_resource *registry; struct pw_resource *registry;
struct pw_context *context = global->context; struct pw_context *context = global->context;
struct pw_impl_client *client;
if (global->registered) if (global->registered)
return -EEXIST; return -EEXIST;
@ -150,8 +151,8 @@ int pw_global_register(struct pw_global *global)
spa_list_for_each(registry, &context->registry_resource_list, link) { spa_list_for_each(registry, &context->registry_resource_list, link) {
uint32_t permissions = pw_global_get_permissions(global, registry->client); uint32_t permissions = pw_global_get_permissions(global, registry->client);
pw_log_debug("registry %p: global %d %08x serial:%"PRIu64, pw_log_debug("registry %p: global %d %08x serial:%"PRIu64" generation:%"PRIu64,
registry, global->id, permissions, global->serial); registry, global->id, permissions, global->serial, global->generation);
if (PW_PERM_IS_R(permissions)) if (PW_PERM_IS_R(permissions))
pw_registry_resource_global(registry, pw_registry_resource_global(registry,
global->id, global->id,
@ -161,6 +162,25 @@ int pw_global_register(struct pw_global *global)
&global->properties->dict); &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_log_debug("%p: registered %u", global, global->id);
pw_context_emit_global_added(context, global); pw_context_emit_global_added(context, global);

View file

@ -300,6 +300,7 @@ struct pw_impl_client {
int recv_seq; /**< last received sequence number */ int recv_seq; /**< last received sequence number */
int send_seq; /**< last sender sequence number */ int send_seq; /**< last sender sequence number */
uint64_t recv_generation; /**< last received registry generation */ uint64_t recv_generation; /**< last received registry generation */
uint64_t sent_generation; /**< last sent registry generation */
void *user_data; /**< extra user data */ void *user_data; /**< extra user data */