aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Orzechowski <alex@ozal.ski>2023-12-06 15:47:24 -0500
committerSimon Ser <contact@emersion.fr>2023-12-13 18:10:03 +0100
commitbbabb9aae8d7b7771d02489b6f20301cf1c090c9 (patch)
tree4f012efa2b612cf580c58596a173520eeb17c40d
parentc6edbb7e5a3e10b4f86a3bee215de5f4c7021674 (diff)
output: Destroy when output layout is destroyed
Since output layout is destroyed when the wayland display is destroyed we run into a destroy listener order problem: Either the display starts destroying the outputs first, in which case we're good: The existing handling will clean up. However, things go wrong if the display decides to destroy the output layout first. In this case, sway will hold invalid references to the output layout as part of each output so that when it finally goes to destroy them, sway will dereference destroyed output layout bits. Ref: https://github.com/swaywm/sway/pull/6844#issuecomment-1843599513
-rw-r--r--include/sway/output.h1
-rw-r--r--sway/desktop/output.c16
2 files changed, 15 insertions, 2 deletions
diff --git a/include/sway/output.h b/include/sway/output.h
index 62d866bc..43cbccd2 100644
--- a/include/sway/output.h
+++ b/include/sway/output.h
@@ -39,6 +39,7 @@ struct sway_output {
struct sway_output_state current;
+ struct wl_listener layout_destroy;
struct wl_listener destroy;
struct wl_listener commit;
struct wl_listener present;
diff --git a/sway/desktop/output.c b/sway/desktop/output.c
index d9328701..d525b2b4 100644
--- a/sway/desktop/output.c
+++ b/sway/desktop/output.c
@@ -892,8 +892,7 @@ static void update_output_manager_config(struct sway_server *server) {
ipc_event_output();
}
-static void handle_destroy(struct wl_listener *listener, void *data) {
- struct sway_output *output = wl_container_of(listener, output, destroy);
+static void begin_destroy(struct sway_output *output) {
struct sway_server *server = output->server;
if (output->enabled) {
@@ -904,6 +903,7 @@ static void handle_destroy(struct wl_listener *listener, void *data) {
wl_list_remove(&output->link);
+ wl_list_remove(&output->layout_destroy.link);
wl_list_remove(&output->destroy.link);
wl_list_remove(&output->commit.link);
wl_list_remove(&output->present.link);
@@ -922,6 +922,16 @@ static void handle_destroy(struct wl_listener *listener, void *data) {
update_output_manager_config(server);
}
+static void handle_destroy(struct wl_listener *listener, void *data) {
+ struct sway_output *output = wl_container_of(listener, output, destroy);
+ begin_destroy(output);
+}
+
+static void handle_layout_destroy(struct wl_listener *listener, void *data) {
+ struct sway_output *output = wl_container_of(listener, output, layout_destroy);
+ begin_destroy(output);
+}
+
static void update_textures(struct sway_container *con, void *data) {
container_update_title_textures(con);
container_update_marks_textures(con);
@@ -1036,6 +1046,8 @@ void handle_new_output(struct wl_listener *listener, void *data) {
output->server = server;
wlr_damage_ring_init(&output->damage_ring);
+ wl_signal_add(&root->output_layout->events.destroy, &output->layout_destroy);
+ output->layout_destroy.notify = handle_layout_destroy;
wl_signal_add(&wlr_output->events.destroy, &output->destroy);
output->destroy.notify = handle_destroy;
wl_signal_add(&wlr_output->events.commit, &output->commit);