Race condition between resource being released and client flush
Server init might happen while a client is being shutdown (splash screen
for instance) in whihc case resources are getting notified and the
client is being scheduled for flush. The client might be in incompatible
state when it's actually flushed.
crrev.com/c/3525425 introduced that paradigm by removing the queue for
flushing.
Change-Id: I6542668869572f7c0b42f5ff0d2895a5e4c4c4ba
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/croscomp/+/3759592
Tested-by: Lucas Berthou <berlu@chromium.org>
Reviewed-by: Jim Shargo <jshargo@chromium.org>
Auto-Submit: Lucas Berthou <berlu@chromium.org>
Reviewed-by: John Plate <jplate@google.com>
Commit-Queue: John Plate <jplate@google.com>
diff --git a/wayland-server/wayland-server.c b/wayland-server/wayland-server.c
index 643c6b4..910887a 100644
--- a/wayland-server/wayland-server.c
+++ b/wayland-server/wayland-server.c
@@ -62,6 +62,7 @@
int error;
struct wl_priv_signal resource_created_signal;
bool needs_flush;
+ bool pending_destroy;
};
struct wl_display {
@@ -215,7 +216,8 @@
handle_array(resource, opcode, args);
- if (!client->needs_flush) {
+ // Do not flush client that are pending destroy to avoid race condition.
+ if (!client->pending_destroy && !client->needs_flush) {
client->needs_flush = true;
flush_client(client);
}
@@ -426,8 +428,10 @@
wl_client_flush(struct wl_client *client)
{
int ret;
+ if (client->pending_destroy)
+ return 0;
- ret = wl_connection_flush(client->connection);
+ ret = wl_connection_flush(client->connection);
if (ret < 0)
return ret;
@@ -839,6 +843,8 @@
{
uint32_t serial = 0;
+ client->pending_destroy = true;
+
wl_priv_signal_final_emit(&client->destroy_signal, client);
wl_client_flush(client);