media-session: pause policy while creating objects

While we are creating objects on the monitor connection, pause the
policy connection until we have completed a roundtrip and the global
id is bound to the new object.

This way, when we resume the policy connection, we can always find the
newly created and bound object. Without the pause, it's possible that
we receive the new global on the policy connection before we got the
bind reply on the monitor connection and then we would end up with 2
proxies that are not linked together correctly.

Fixes #204
This commit is contained in:
Wim Taymans 2020-01-14 16:38:40 +01:00
parent 0ea8a92ea5
commit c21c42e943

View file

@ -98,6 +98,7 @@ struct impl {
struct pw_core *monitor_core; struct pw_core *monitor_core;
struct spa_hook monitor_listener; struct spa_hook monitor_listener;
int monitor_seq;
struct pw_core *policy_core; struct pw_core *policy_core;
struct spa_hook policy_listener; struct spa_hook policy_listener;
@ -953,7 +954,8 @@ static void bound_proxy(void *data, uint32_t id)
struct sm_object *obj = data; struct sm_object *obj = data;
struct impl *impl = SPA_CONTAINER_OF(obj->session, struct impl, this); struct impl *impl = SPA_CONTAINER_OF(obj->session, struct impl, this);
pw_log_debug("bound %p proxy %p id:%d->%d", obj, obj->proxy, obj->id, id); pw_log_debug("bound %p proxy %p handle %p id:%d->%d",
obj, obj->proxy, obj->handle, obj->id, id);
if (obj->id == SPA_ID_INVALID) if (obj->id == SPA_ID_INVALID)
add_object(impl, obj, id); add_object(impl, obj, id);
@ -1256,14 +1258,28 @@ static const struct pw_registry_events registry_events = {
.global_remove = registry_global_remove, .global_remove = registry_global_remove,
}; };
static void monitor_sync(struct impl *impl)
{
pw_core_set_paused(impl->policy_core, true);
impl->monitor_seq = pw_core_sync(impl->monitor_core, 0, impl->monitor_seq);
pw_log_debug(NAME " %p: monitor sync start %d", impl, impl->monitor_seq);
}
struct pw_proxy *sm_media_session_export(struct sm_media_session *sess, struct pw_proxy *sm_media_session_export(struct sm_media_session *sess,
const char *type, const struct spa_dict *props, const char *type, const struct spa_dict *props,
void *object, size_t user_data_size) void *object, size_t user_data_size)
{ {
struct impl *impl = SPA_CONTAINER_OF(sess, struct impl, this); struct impl *impl = SPA_CONTAINER_OF(sess, struct impl, this);
struct pw_proxy *handle;
pw_log_debug(NAME " %p: object %s %p", impl, type, object); pw_log_debug(NAME " %p: object %s %p", impl, type, object);
return pw_core_export(impl->monitor_core, type,
handle = pw_core_export(impl->monitor_core, type,
props, object, user_data_size); props, object, user_data_size);
monitor_sync(impl);
return handle;
} }
struct sm_node *sm_media_session_export_node(struct sm_media_session *sess, struct sm_node *sm_media_session_export_node(struct sm_media_session *sess,
@ -1280,6 +1296,8 @@ struct sm_node *sm_media_session_export_node(struct sm_media_session *sess,
node = (struct sm_node *) create_object(impl, NULL, handle, props); node = (struct sm_node *) create_object(impl, NULL, handle, props);
monitor_sync(impl);
return node; return node;
} }
@ -1297,6 +1315,8 @@ struct sm_device *sm_media_session_export_device(struct sm_media_session *sess,
device = (struct sm_device *) create_object(impl, NULL, handle, props); device = (struct sm_device *) create_object(impl, NULL, handle, props);
monitor_sync(impl);
return device; return device;
} }
@ -1521,6 +1541,21 @@ int sm_media_session_create_links(struct sm_media_session *sess,
return res; return res;
} }
static void monitor_core_done(void *data, uint32_t id, int seq)
{
struct impl *impl = data;
if (seq == impl->monitor_seq) {
pw_log_debug(NAME " %p: monitor sync stop %d", impl, seq);
pw_core_set_paused(impl->policy_core, false);
}
}
static const struct pw_core_events monitor_core_events = {
PW_VERSION_CORE_EVENTS,
.done = monitor_core_done,
};
static int start_session(struct impl *impl) static int start_session(struct impl *impl)
{ {
impl->monitor_core = pw_context_connect(impl->this.context, NULL, 0); impl->monitor_core = pw_context_connect(impl->this.context, NULL, 0);
@ -1528,6 +1563,11 @@ static int start_session(struct impl *impl)
pw_log_error("can't start monitor: %m"); pw_log_error("can't start monitor: %m");
return -errno; return -errno;
} }
pw_core_add_listener(impl->monitor_core,
&impl->monitor_listener,
&monitor_core_events, impl);
return 0; return 0;
} }
@ -1584,7 +1624,7 @@ static void core_error(void *data, uint32_t id, int seq, int res, const char *me
} }
static const struct pw_core_events core_events = { static const struct pw_core_events policy_core_events = {
PW_VERSION_CORE_EVENTS, PW_VERSION_CORE_EVENTS,
.info = core_info, .info = core_info,
.done = core_done, .done = core_done,
@ -1613,7 +1653,7 @@ static int start_policy(struct impl *impl)
pw_core_add_listener(impl->policy_core, pw_core_add_listener(impl->policy_core,
&impl->policy_listener, &impl->policy_listener,
&core_events, impl); &policy_core_events, impl);
pw_proxy_add_listener((struct pw_proxy*)impl->policy_core, pw_proxy_add_listener((struct pw_proxy*)impl->policy_core,
&impl->proxy_policy_listener, &impl->proxy_policy_listener,
&proxy_core_events, impl); &proxy_core_events, impl);