media-session: deal with global id race conditions

To resolve monitor and policy core global ids racing with each other,
use separate registry event handlers for both cores.  Each handles only
their own objects, determined by where the object handle was created.

Postpone handling of policy core new global events after monitor sync,
which orders them after the corresponding monitor proxy and registry
events. Monitor core is then more up-to-date, so we resolve id clashes
in favor of monitor globals, which avoids duplicate objects.

Fix use-after-free by tracking whether a monitor holds references to
sm_object. Keep also objects pending for id in a list, so that they can
be cleaned up on session_shutdown (monitors may leak objects at
shutdown, because spa objectinfo events won't be handled then).

Caveats:

Zombie objects may still created if policy core is late by several
events, but in those cases the corresponding remove events are already
in the queue.

Also, there's a (theoretical) possibility that pw_registry_bind will
bind the wrong object, if the registry event is handled too late and an
id is reused by the server.

For details, see reverted 77e4fdb1e4
for which this is a another approach.
This commit is contained in:
Pauli Virtanen 2021-02-27 14:55:13 +02:00 committed by Wim Taymans
parent 864d0148c2
commit 5b8c7c405d
5 changed files with 330 additions and 116 deletions

View file

@ -83,6 +83,10 @@ struct sm_object {
struct spa_callbacks methods;
struct spa_list data;
unsigned int monitor_global:1; /**< whether handle is from monitor core */
unsigned int destroyed:1; /**< whether proxies have been destroyed */
unsigned int discarded:1; /**< whether monitors hold no references */
};
int sm_object_add_listener(struct sm_object *obj, struct spa_hook *listener,
@ -109,6 +113,8 @@ int sm_object_sync_update(struct sm_object *obj);
int sm_object_destroy(struct sm_object *obj);
#define sm_object_discard(o) do { (o)->discarded = true; } while (0)
struct sm_client {
struct sm_object obj;