mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-04 13:30:12 -05:00
impl-core/protocol-native: use generation counter for global registry
Some client messages have bare ids (as opposed to proxies/resources),
eg. as in pw_registry_bind/destroy. If the client is processing
messages late, these may refer to an object that was already removed,
and the id may now refers to a differnt objects. I.e. the following
race condition needs to be resolved:
server client
Global 1 (gen. 1)
Global 1
Global 1 remove
Global 1 (gen. 2)
Bind/destroy 1
Where the client would bind/destroy the wrong global, since it did not
yet see the messages for the second one.
To keep track of which object the client means, the server keeps track of
the "generation number" of its global registry, and what generation
the client is at.
Each global remembers at what generation of registry they were
registered. When processing the messages that use bare ids, check the
registry generation of the client, to know whether the message refers to
a stale global that was already removed.
Messages where client sends bare ids to server are:
pw_registry_bind, pw_registry_destroy, metadata_set_property
In pw_registry_* do the staleness check directly. Also add staleness
check in pw_impl_client_check_permissions, so that also the metadata
case is handled.
The generation numbers are passed around in message footers, but only if
they have changed. When the generation number changes on server, we
send the updated value to the client in a message footer. When client
has received an update value, it will send the value back in the footer
of the next message it sends to the server.
Based on: Wim Taymans <wtaymans@redhat.com> "impl-core: check serial number"
This commit is contained in:
parent
680c33d3eb
commit
d44bf0ffc0
6 changed files with 91 additions and 4 deletions
|
|
@ -76,6 +76,17 @@ void marshal_proxy_footers(struct footer_proxy_global_state *state, struct pw_pr
|
|||
{
|
||||
struct footer_builder fb = FOOTER_BUILDER_INIT(builder);
|
||||
|
||||
if (proxy->core->recv_generation != state->last_recv_generation) {
|
||||
state->last_recv_generation = proxy->core->recv_generation;
|
||||
|
||||
pw_log_trace("core %p: send client registry generation:%"PRIu64,
|
||||
proxy->core, proxy->core->recv_generation);
|
||||
|
||||
start_footer_entry(&fb, FOOTER_RESOURCE_OPCODE_GENERATION);
|
||||
spa_pod_builder_long(fb.builder, proxy->core->recv_generation);
|
||||
end_footer_entry(&fb);
|
||||
}
|
||||
|
||||
end_footer(&fb);
|
||||
}
|
||||
|
||||
|
|
@ -84,11 +95,56 @@ void marshal_resource_footers(struct footer_resource_global_state *state, struct
|
|||
{
|
||||
struct footer_builder fb = FOOTER_BUILDER_INIT(builder);
|
||||
|
||||
if (resource->context->generation != state->last_sent_generation) {
|
||||
state->last_sent_generation = resource->context->generation;
|
||||
|
||||
pw_log_trace("impl-client %p: send server registry generation:%"PRIu64,
|
||||
resource->client, resource->context->generation);
|
||||
|
||||
start_footer_entry(&fb, FOOTER_RESOURCE_OPCODE_GENERATION);
|
||||
spa_pod_builder_long(fb.builder, resource->context->generation);
|
||||
end_footer_entry(&fb);
|
||||
}
|
||||
|
||||
end_footer(&fb);
|
||||
}
|
||||
|
||||
int demarshal_proxy_generation(void *object, struct spa_pod_parser *parser)
|
||||
{
|
||||
struct pw_proxy *proxy = object;
|
||||
int64_t generation;
|
||||
|
||||
if (spa_pod_parser_get_long(parser, &generation) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
proxy->core->recv_generation = (uint64_t)generation;
|
||||
|
||||
pw_log_trace("core %p: recv server registry generation:%"PRIu64,
|
||||
proxy->core, generation);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int demarshal_resource_generation(void *object, struct spa_pod_parser *parser)
|
||||
{
|
||||
struct pw_resource *resource = object;
|
||||
int64_t generation;
|
||||
|
||||
if (spa_pod_parser_get_long(parser, &generation) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
resource->client->recv_generation = (uint64_t)generation;
|
||||
|
||||
pw_log_trace("impl-client %p: recv client registry generation:%"PRIu64,
|
||||
resource->client, generation);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct footer_demarshal footer_proxy_demarshal[FOOTER_PROXY_OPCODE_LAST] = {
|
||||
[FOOTER_PROXY_OPCODE_GENERATION] = (struct footer_demarshal){ .demarshal = demarshal_proxy_generation },
|
||||
};
|
||||
|
||||
const struct footer_demarshal footer_resource_demarshal[FOOTER_RESOURCE_OPCODE_LAST] = {
|
||||
[FOOTER_RESOURCE_OPCODE_GENERATION] = (struct footer_demarshal){ .demarshal = demarshal_resource_generation },
|
||||
};
|
||||
|
|
|
|||
|
|
@ -30,17 +30,21 @@
|
|||
*/
|
||||
|
||||
enum {
|
||||
FOOTER_PROXY_OPCODE_LAST = 0,
|
||||
FOOTER_PROXY_OPCODE_GENERATION = 0,
|
||||
FOOTER_PROXY_OPCODE_LAST
|
||||
};
|
||||
|
||||
enum {
|
||||
FOOTER_RESOURCE_OPCODE_LAST = 0,
|
||||
FOOTER_RESOURCE_OPCODE_GENERATION = 0,
|
||||
FOOTER_RESOURCE_OPCODE_LAST
|
||||
};
|
||||
|
||||
struct footer_proxy_global_state {
|
||||
uint64_t last_recv_generation;
|
||||
};
|
||||
|
||||
struct footer_resource_global_state {
|
||||
uint64_t last_sent_generation;
|
||||
};
|
||||
|
||||
struct footer_demarshal {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue