proxy: improve proxy cleanup

When we destroy a proxy, mark it as zombie until the server removes
the id. This way we can still keep the id locked with a valid entry
and remove it later.
This commit is contained in:
Wim Taymans 2019-08-14 11:46:07 +02:00
parent d86e462dca
commit 35f617157f
4 changed files with 26 additions and 16 deletions

View file

@ -533,9 +533,13 @@ on_remote_data(void *data, int fd, uint32_t mask)
} }
proxy = pw_remote_find_proxy(this, msg->id); proxy = pw_remote_find_proxy(this, msg->id);
if (proxy == NULL || proxy->zombie) {
if (proxy->zombie)
pw_log_debug(NAME" %p: zombie proxy %u", this, msg->id);
else
pw_log_error(NAME" %p: could not find proxy %u", this, msg->id);
if (proxy == NULL) { /* FIXME close fds */
pw_log_error("protocol-native %p: could not find proxy %u", this, msg->id);
continue; continue;
} }

View file

@ -655,6 +655,8 @@ struct pw_proxy {
struct spa_list link; /**< link in the remote */ struct spa_list link; /**< link in the remote */
uint32_t id; /**< client side id */ uint32_t id; /**< client side id */
unsigned int zombie:1; /**< proxy is removed locally and waiting to
* be removed from server */
unsigned int removed:1; /**< proxy was removed from server */ unsigned int removed:1; /**< proxy was removed from server */
struct spa_hook_list listener_list; struct spa_hook_list listener_list;

View file

@ -161,22 +161,27 @@ void pw_proxy_destroy(struct pw_proxy *proxy)
struct proxy *impl = SPA_CONTAINER_OF(proxy, struct proxy, this); struct proxy *impl = SPA_CONTAINER_OF(proxy, struct proxy, this);
struct pw_remote *remote = proxy->remote; struct pw_remote *remote = proxy->remote;
if (!proxy->zombie) {
pw_log_debug(NAME" %p: destroy %u", proxy, proxy->id); pw_log_debug(NAME" %p: destroy %u", proxy, proxy->id);
pw_proxy_emit_destroy(proxy); pw_proxy_emit_destroy(proxy);
spa_list_remove(&proxy->link); spa_list_remove(&proxy->link);
}
if (!proxy->removed) { if (!proxy->removed) {
/* if the server did not remove this proxy, remove ourselves /* if the server did not remove this proxy, remove ourselves
* from the proxy objects and schedule a destroy, if * from the proxy objects and schedule a destroy. */
* we don't have a remote, we must keep the proxy id if (remote->core_proxy) {
* locked because the server might be using it still. */ proxy->zombie = true;
pw_map_insert_at(&remote->objects, proxy->id, NULL);
if (remote->core_proxy)
pw_core_proxy_destroy(remote->core_proxy, proxy); pw_core_proxy_destroy(remote->core_proxy, proxy);
} else {
proxy->removed = true;
} }
pw_log_debug(NAME" %p: free", proxy); }
if (proxy->removed) {
pw_map_remove(&remote->objects, proxy->id);
pw_log_debug(NAME" %p: free %u", proxy, proxy->id);
free(impl); free(impl);
}
} }
SPA_EXPORT SPA_EXPORT

View file

@ -141,7 +141,6 @@ static void core_event_remove_id(void *data, uint32_t id)
if ((proxy = pw_map_lookup(&this->objects, id)) != NULL) { if ((proxy = pw_map_lookup(&this->objects, id)) != NULL) {
proxy->removed = true; proxy->removed = true;
pw_proxy_destroy(proxy); pw_proxy_destroy(proxy);
pw_map_remove(&this->objects, id);
} }
} }