Skip to content
Browse files

server: add wl_global_remove

This commit adds a new wl_global_remove function that just sends a global
remove event without destroying it. See [1] for details.

Removing a global is racy, because clients have no way to acknowledge they
received the removal event.

It's possible to mitigate the issue by sending the removal event, waiting a
little and then destructing the global for real. The "wait a little" part is
compositor policy.


Signed-off-by: Simon Ser <>
  • Loading branch information
emersion committed Jul 20, 2019
1 parent 11623e8 commit 39852f1146941fa93daf767b4ecfb41b2d11aaef
Showing with 43 additions and 2 deletions.
  1. +3 −0 src/wayland-server-core.h
  2. +40 −2 src/wayland-server.c
@@ -246,6 +246,9 @@ wl_global_create(struct wl_display *display,
int version,
void *data, wl_global_bind_func_t bind);

wl_global_remove(struct wl_global *global);

wl_global_destroy(struct wl_global *global);

@@ -25,6 +25,7 @@

#define _GNU_SOURCE

#include <stdbool.h>
#include <stdlib.h>
#include <stdint.h>
#include <stddef.h>
@@ -112,6 +113,7 @@ struct wl_global {
void *data;
wl_global_bind_func_t bind;
struct wl_list link;
bool removed;

struct wl_resource {
@@ -992,7 +994,7 @@ display_get_registry(struct wl_client *client,

wl_list_for_each(global, &display->global_list, link)
if (wl_global_is_visible(client, global))
if (wl_global_is_visible(client, global) && !global->removed)
@@ -1208,6 +1210,7 @@ wl_global_create(struct wl_display *display,
global->version = version;
global->data = data;
global->bind = bind;
global->removed = false;
wl_list_insert(display->global_list.prev, &global->link);

wl_list_for_each(resource, &display->registry_resource_list, link)
@@ -1220,15 +1223,50 @@ wl_global_create(struct wl_display *display,
return global;

/** Remove the global
* \param global The Wayland global.
* Broadcast a global remove event to all clients without destroying the
* global. This function can only be called once per global.
* wl_global_destroy() removes the global and immediately destroys it. On
* the other end, this function only removes the global, allowing clients
* that have not yet received the global remove event to continue to bind to
* it.
* This can be used by compositors to mitigate clients being disconnected
* because a global has been added and removed too quickly. Compositors can call
* wl_global_remove(), then wait an implementation-defined amount of time, then
* call wl_global_destroy(). Note that the destruction of a global is still
* racy, since clients have no way to acknowledge that they received the remove
* event.
* \since 1.17.90
wl_global_destroy(struct wl_global *global)
wl_global_remove(struct wl_global *global)
struct wl_display *display = global->display;
struct wl_resource *resource;

if (global->removed)
wl_abort("wl_global_remove: called twice on the same "
"global '%s@%"PRIu32"'", global->interface->name,

wl_list_for_each(resource, &display->registry_resource_list, link)
wl_resource_post_event(resource, WL_REGISTRY_GLOBAL_REMOVE,

global->removed = true;

wl_global_destroy(struct wl_global *global)
if (!global->removed)

0 comments on commit 39852f1

Please sign in to comment.
You can’t perform that action at this time.