Skip to content
This repository was archived by the owner on Jan 26, 2024. It is now read-only.

Segfault when there's a layer surface on a monitor being disconnected #314

Closed
BenJarg opened this issue Oct 1, 2022 · 25 comments
Closed
Labels
A: bug Something isn't working

Comments

@BenJarg
Copy link
Contributor

BenJarg commented Oct 1, 2022

Info

dwl's commit: b5776e5
wlroots version: 0.15.1

Description

Where I start a instance of yambar on an external monitor, then disconnect it, dwl crashes with a segfault. I can also trigger this by opening rofi (the wayland fork) on the externel monitor, then disconnect the monitor before closing it.

The stacktrace doesn't seem that helpful unfortunately:

Process terminating with default action of signal 11 (SIGSEGV)
 Access not within mapped region at address 0x0
   at 0x49430E3: wl_list_insert (wayland-util.c:50)
   by 0x48ED1A8: wlr_signal_emit_safe (signal.c:17)
   by 0x48B9898: wlr_output_schedule_frame (output.c:804)
   by 0x48BEB55: scene_surface_handle_surface_commit (wlr_scene.c:261)
   by 0x48ED1EB: wlr_signal_emit_safe (signal.c:29)
   by 0x5157E6C: ??? (in /usr/lib/libffi.so.7.1.0)
   by 0x51572A9: ??? (in /usr/lib/libffi.so.7.1.0)
   by 0x49420B4: wl_closure_invoke.constprop.0 (connection.c:1025)
   by 0x49462DB: wl_client_connection_data (wayland-server.c:437)
   by 0x4944E21: wl_event_loop_dispatch (event-loop.c:1027)
   by 0x4945574: wl_display_run (wayland-server.c:1431)
   by 0x115A4B: run (dwl.c:1879)
   by 0x115A4B: main (dwl.c:2675)

In a dump from valgrind, I got an additional error just before that stacktrace that may be more insightful:

Invalid write of size 8
   at 0x49433B7: wl_list_remove (wayland-util.c:56)
   by 0x110332: destroylayersurfacenotify (dwl.c:1098)
   by 0x48ED1EB: wlr_signal_emit_safe (signal.c:29)
   by 0x48DA08E: layer_surface_destroy (wlr_layer_shell_v1.c:283)
   by 0x4944CDE: destroy_resource (wayland-server.c:730)
   by 0x4946971: wl_resource_destroy (wayland-server.c:747)
   by 0x5157E6C: ??? (in /usr/lib/libffi.so.7.1.0)
   by 0x51572A9: ??? (in /usr/lib/libffi.so.7.1.0)
   by 0x49420B4: wl_closure_invoke.constprop.0 (connection.c:1025)
   by 0x49462DB: wl_client_connection_data (wayland-server.c:437)
   by 0x4944E21: wl_event_loop_dispatch (event-loop.c:1027)
   by 0x4945574: wl_display_run (wayland-server.c:1431)
 Address 0x201b75e8 is 120 bytes inside a block of size 248 free'd
   at 0x483C0FB: free (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
   by 0x1149E7: cleanupmon (dwl.c:778)
   by 0x48ED1EB: wlr_signal_emit_safe (signal.c:29)
   by 0x48BCAA1: UnknownInlinedFun (output.c:429)
   by 0x48BCAA1: wlr_output_destroy (output.c:420)
   by 0x48A6FF3: UnknownInlinedFun (drm.c:1540)
   by 0x48A6FF3: scan_drm_connectors (drm.c:1384)
   by 0x48ED1EB: wlr_signal_emit_safe (signal.c:29)
   by 0x48B8AB8: handle_udev_event (session.c:214)
   by 0x4944E21: wl_event_loop_dispatch (event-loop.c:1027)
   by 0x4945574: wl_display_run (wayland-server.c:1431)
   by 0x115A4B: run (dwl.c:1879)
   by 0x115A4B: main (dwl.c:2675)
 Block was alloc'd at
   at 0x483E581: calloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
   by 0x115CBE: ecalloc (in /home/bjargowsky/Documents/Projects/dwl/dwl)
   by 0x111D0B: createmon (dwl.c:935)
   by 0x48ED1EB: wlr_signal_emit_safe (signal.c:29)
   by 0x48ED1EB: wlr_signal_emit_safe (signal.c:29)
   by 0x48A7185: scan_drm_connectors (drm.c:1413)
   by 0x48A8356: backend_start (backend.c:25)
   by 0x48B3AC4: multi_backend_start (backend.c:33)
   by 0x11585E: run (dwl.c:1839)
   by 0x11585E: main (dwl.c:2675)

I assume closemon() should be doing something to avoid this.

@BenJarg BenJarg added the A: bug Something isn't working label Oct 1, 2022
@sevz17
Copy link
Collaborator

sevz17 commented Oct 1, 2022

Maybe applying this?

diff --git a/dwl.c b/dwl.c
index 2e00799..3d88751 100644
--- a/dwl.c
+++ b/dwl.c
@@ -759,16 +759,22 @@ void
 cleanupmon(struct wl_listener *listener, void *data)
 {
 	Monitor *m = wl_container_of(listener, m, destroy);
-	int nmons, i = 0;
+	LayerSurface *l;
+	int nmons, i;
 
 	wl_list_remove(&m->destroy.link);
 	wl_list_remove(&m->frame.link);
 	wl_list_remove(&m->link);
 	m->wlr_output->data = NULL;
+
+	for (i = 0; i >= ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY; i++)
+		wl_list_for_each(l, &m->layers[i], link)
+			wlr_layer_surface_v1_destroy(l->layer_surface);
+
 	wlr_output_layout_remove(output_layout, m->wlr_output);
 	wlr_scene_output_destroy(m->scene_output);
 
-	if ((nmons = wl_list_length(&mons)))
+	if ((i = 0) || (nmons = wl_list_length(&mons)))
 		do /* don't switch to disabled mons */
 			selmon = wl_container_of(mons.prev, selmon, link);
 		while (!selmon->wlr_output->enabled && i++ < nmons);

@sevz17
Copy link
Collaborator

sevz17 commented Oct 1, 2022

Or this:

diff --git a/dwl.c b/dwl.c
index 2e00799..6f85555 100644
--- a/dwl.c
+++ b/dwl.c
@@ -764,6 +764,8 @@ cleanupmon(struct wl_listener *listener, void *data)
 	wl_list_remove(&m->destroy.link);
 	wl_list_remove(&m->frame.link);
 	wl_list_remove(&m->link);
+	for (i = 0; i >= ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY; i++)
+		wl_list_remove(&m->layers[i]);
 	m->wlr_output->data = NULL;
 	wlr_output_layout_remove(output_layout, m->wlr_output);
 	wlr_scene_output_destroy(m->scene_output);

@fauxmight
Copy link

fauxmight commented Oct 1, 2022

@sev17: What should happen when the last monitor is disconnected? Is this considered undefined behavior? Should clients remain in last known position until a new monitor is attached? Is dwl expected to die in this circumstance?

Currently (with layer surface clients in play on all monitors) if I disconnect the only [edit] remaining [/edit] monitor (via a kvm switch), and then return kvm connection seconds or minutes later, dwl is dead and I have to restart. This may be due to this bug listed; I have not tried the proposed patches yet or checked whether dwl dies when no layer shell is present, but it may be intended behavior, so I am asking here instead of starting a new bug.

@BenJarg
Copy link
Contributor Author

BenJarg commented Oct 1, 2022

@sevz17 Neither of those patches seem to fix this (error looks the same in valgrind as well)

@sevz17
Copy link
Collaborator

sevz17 commented Oct 1, 2022

@sev17: What should happen when the last monitor is disconnected? Is this considered undefined behavior? Should clients remain in last known position until a new monitor is attached? Is dwl expected to die in this circumstance?

I'm unsure about clients, but definitely I don't want dwl to die

Currently (with layer surface clients in play on all monitors) if I disconnect the only [edit] remaining [/edit] monitor (via a kvm switch), and then return kvm connection seconds or minutes later, dwl is dead and I have to restart. This may be due to this bug listed

Maybe, lets see if solving this issue fixes it

@BenJarg BenJarg changed the title Segfaul when there's a layer surface on a monitor being disconnected Segfault when there's a layer surface on a monitor being disconnected Oct 1, 2022
@sevz17
Copy link
Collaborator

sevz17 commented Oct 1, 2022

@BenJarg can you apply this and send me the dwl output?

diff --git a/dwl.c b/dwl.c
index c8364e9..f21fb32 100644
--- a/dwl.c
+++ b/dwl.c
@@ -2666,6 +2666,7 @@ main(int argc, char *argv[])
 	/* Wayland requires XDG_RUNTIME_DIR for creating its communications socket */
 	if (!getenv("XDG_RUNTIME_DIR"))
 		die("XDG_RUNTIME_DIR must be set");
+	wlr_log_init(WLR_DEBUG, NULL);
 	setup();
 	run(startup_cmd);
 	cleanup();

@BenJarg
Copy link
Contributor Author

BenJarg commented Oct 1, 2022

Starting from where I opened yambar on the external monitor (calling yambar from Tilix terminal), then disconnect the monitor, ending with where is segfaults:

00:01:58.295 [DEBUG] [types/wlr_surface.c:748] New wlr_surface 0x556081596d60 (res 0x556081144e70)
00:01:58.295 [DEBUG] [types/wlr_surface.c:748] New wlr_surface 0x55608151e9e0 (res 0x55608151ed20)
00:01:58.295 [DEBUG] [types/wlr_layer_shell_v1.c:472] new layer_surface 0x55608150b6e0 (res 0x556081500a20)
00:02:14.221 [DEBUG] [backend/session/session.c:182] udev event for card0 (change)
00:02:14.221 [DEBUG] [backend/session/session.c:211] DRM device card0 changed
00:02:14.221 [DEBUG] [backend/drm/backend.c:138] Received hotplug event for /dev/dri/card0
00:02:14.221 [INFO] [backend/drm/drm.c:1182] Scanning DRM connector 83 on /dev/dri/card0
00:02:14.221 [INFO] [backend/drm/drm.c:1383] 'HDMI-A-1' disconnected
eDP-1 title 
eDP-1 fullscreen 
eDP-1 floating 
eDP-1 selmon 1
eDP-1 tags 0 1 0 0
eDP-1 layout  舘 
eDP-1 title Tilix
eDP-1 fullscreen 0
eDP-1 floating 0
eDP-1 selmon 1
eDP-1 tags 1 1 1 0
eDP-1 layout  舘 
eDP-1 title Tilix
eDP-1 fullscreen 0
eDP-1 floating 0
eDP-1 selmon 1
eDP-1 tags 1 1 1 0
eDP-1 layout  舘 
eDP-1 title Tilix
eDP-1 fullscreen 0
eDP-1 floating 0
eDP-1 selmon 1
eDP-1 tags 1 1 1 0
eDP-1 layout  舘 
00:02:14.222 [DEBUG] [backend/drm/drm.c:1017] connector HDMI-A-1: De-allocating CRTC 1
00:02:14.252 [DEBUG] [backend/drm/drm.c:1047] Reallocating CRTCs
00:02:14.252 [DEBUG] [backend/drm/drm.c:1058] State before reallocation:
00:02:14.252 [DEBUG] [backend/drm/drm.c:1064]   'eDP-1' crtc=0 status=3 desired_enabled=1
00:02:14.252 [DEBUG] [backend/drm/drm.c:1064]   'HDMI-A-1' crtc=-1 status=0 desired_enabled=0
00:02:14.252 [DEBUG] [backend/drm/drm.c:1064]   'DP-1' crtc=-1 status=0 desired_enabled=0
00:02:14.252 [DEBUG] [backend/drm/drm.c:1064]   'DP-2' crtc=-1 status=0 desired_enabled=0
00:02:14.252 [DEBUG] [backend/drm/drm.c:1115] State after reallocation:
00:02:14.252 [DEBUG] [backend/drm/drm.c:1122]   'eDP-1' crtc=0 status=3 desired_enabled=1
00:02:14.252 [DEBUG] [backend/drm/drm.c:1122]   'HDMI-A-1' crtc=-1 status=0 desired_enabled=0
00:02:14.252 [DEBUG] [backend/drm/drm.c:1122]   'DP-1' crtc=-1 status=0 desired_enabled=0
00:02:14.252 [DEBUG] [backend/drm/drm.c:1122]   'DP-2' crtc=-1 status=0 desired_enabled=0
Gdk-Message: 16:22:02.494: Error reading events from display: Broken pipe

@sevz17
Copy link
Collaborator

sevz17 commented Oct 2, 2022

this one?

diff --git a/dwl.c b/dwl.c
index 2e00799..8abb93b 100644
--- a/dwl.c
+++ b/dwl.c
@@ -2353,6 +2353,8 @@ unmaplayersurfacenotify(struct wl_listener *listener, void *data)
 	LayerSurface *layersurface = wl_container_of(listener, layersurface, unmap);
 
 	layersurface->mapped = 0;
+	wlr_surface_send_leave(layersurface->layer_surface->surface,
+			layersurface->layer_surface->output);
 	wlr_scene_node_set_enabled(layersurface->scene, 0);
 	if (layersurface == exclusive_focus)
 		exclusive_focus = NULL;

@BenJarg
Copy link
Contributor Author

BenJarg commented Oct 2, 2022

@sevz17 Still segfaults unfortunately

@sevz17
Copy link
Collaborator

sevz17 commented Oct 2, 2022

The same backtrace?

@BenJarg
Copy link
Contributor Author

BenJarg commented Oct 2, 2022

@sevz17 Yes that's right

@sevz17
Copy link
Collaborator

sevz17 commented Oct 2, 2022

Can you reproduce it in this commit?
if so, in this commit?

@BenJarg
Copy link
Contributor Author

BenJarg commented Oct 2, 2022

@sevz17 The issue is present in both, with the same backtrace as before.

@sevz17
Copy link
Collaborator

sevz17 commented Oct 2, 2022

Mmm, then I highly suspect it is something from wlroots, but until I can prove it, let's assume it's our fault.

@sevz17
Copy link
Collaborator

sevz17 commented Oct 2, 2022

@BenJarg, I've just merge main into wlroots-next branch, please can you install wlroots-git and see if this can be reproduced on it?

@sevz17
Copy link
Collaborator

sevz17 commented Oct 2, 2022

And... if I don't abuse of your help, can you check https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/3740 if wlroots' master branch still segfaults?

NOTE: if you can't or not willing to do so, don't worry I appreciate the help so far

@BenJarg
Copy link
Contributor Author

BenJarg commented Oct 2, 2022

@sevz17 Good news, running wlroots-next on the current upstream of wlroots (https://gitlab.freedesktop.org/wlroots/wlroots/-/commit/b7e2a2584e99f0b11d564a5cc9c44fc5ba974a3d) no longer produces a segfault. There is some other (less severe) not ideal behavior though:
When yambar is on the second monitor, then the monitor is disconnected, yambar is no longer visible (it doesn't move to another monitor). Then when the monitor is plugged back in, the yambar instance starts showing again. But when windows are opened on the second monitor, clients now overlap with yambar, that is, yambar lost it's exclusion zone.

@sevz17
Copy link
Collaborator

sevz17 commented Oct 4, 2022

Good, less work :)

About the layer surfaces, probably we should just destroy them when its monitor is destroyed.

@sevz17
Copy link
Collaborator

sevz17 commented Oct 8, 2022

@BenJarg, please can you try this patch in main branch?

diff --git a/dwl.c b/dwl.c
index fc8f7b2..9f075b4 100644
--- a/dwl.c
+++ b/dwl.c
@@ -764,6 +764,8 @@ cleanupmon(struct wl_listener *listener, void *data)
 	Monitor *m = wl_container_of(listener, m, destroy);
 	int nmons, i = 0;
 
+	wlr_output_enable(m->wlr_output, 0);
+	wlr_output_commit(m->wlr_output);
 	wl_list_remove(&m->destroy.link);
 	wl_list_remove(&m->frame.link);
 	wl_list_remove(&m->link);

@BenJarg
Copy link
Contributor Author

BenJarg commented Oct 9, 2022

@sevz17 The behavior is the same, and the backtrace also seems to be the same.

@sevz17
Copy link
Collaborator

sevz17 commented Oct 9, 2022

Can you give me the output of bt full in gdb please?

@BenJarg
Copy link
Contributor Author

BenJarg commented Oct 11, 2022

@sevz17 Here's the output with your last patch applied on the current main branch (7656569):

#0  0x00007ffff7ecf0e3 in wl_list_insert (list=list@entry=0x555556067b40, elm=elm@entry=0x7fffffffdcd0) at ../src/wayland-util.c:50
No locals.
#1  0x00007ffff7f651a9 in wlr_signal_emit_safe (signal=0x555556067b40, data=0x5555560679a0) at ../util/signal.c:17
        cursor = {link = {prev = 0x555556067b40, next = 0x0}, notify = 0x5555561c8db0}
        end = {link = {prev = 0x55555626a830, next = 0x7fffffffdb78}, notify = 0x0}
#2  0x00007ffff7f31899 in wlr_output_schedule_frame (output=0x5555560679a0) at ../types/output/output.c:804
        ev = <optimized out>
#3  0x00007ffff7f36b56 in scene_surface_handle_surface_commit (listener=0x5555562115f8, data=<optimized out>) at ../types/scene/wlr_scene.c:261
        scene_surface = 0x555556211570
        surface = 0x5555561c8d90
        scene = 0x555555590640
        lx = 1920
        ly = 0
        enabled = true
        scene_output = <optimized out>
#4  0x00007ffff7f651ec in wlr_signal_emit_safe (signal=<optimized out>, data=0x5555561c8d90) at ../util/signal.c:29
        pos = 0x5555562115f8
        l = 0x5555562115f8
        cursor = {link = {prev = 0x5555562115f8, next = 0x5555562114c8}, notify = 0x7ffff7f628b0 <handle_noop>}
        end = {link = {prev = 0x5555562114c8, next = 0x5555561c9040}, notify = 0x7ffff7f628b0 <handle_noop>}
#5  0x00007ffff78c8e6d in ?? () from target:/usr/lib/libffi.so.7
No symbol table info available.
#6  0x00007ffff78c82aa in ?? () from target:/usr/lib/libffi.so.7
No symbol table info available.
#7  0x00007ffff7ece0b5 in wl_closure_invoke (closure=closure@entry=0x5555560c91d0, target=<optimized out>, target@entry=0x5555561c8b80, opcode=opcode@entry=6, data=<optimized out>, data@entry=0x5555562c30a0, flags=<optimized out>) at ../src/connection.c:1025
        count = <optimized out>
        cif = {abi = FFI_UNIX64, nargs = 2, arg_types = 0x7fffffffdf60, rtype = 0x7ffff78ca180 <ffi_type_void>, bytes = 0, flags = 0}
        ffi_types = {0x7ffff78ca060 <ffi_type_pointer>, 0x7ffff78ca060 <ffi_type_pointer>, 0x7ffff78ca0e0 <ffi_type_uint32>, 0x7ffff78ca0c0 <ffi_type_sint32>, 0x7ffff78ca0c0 <ffi_type_sint32>, 0x7ffff78ca0c0 <ffi_type_sint32>, 0x7ffff7fa7200 <xdg_toplevel_events.lto_priv>, 0x5555562bebb0, 0x555555e55770, 0x1c, 0x0, 
          0x7ffff7eccb75 <wl_closure_close_fds+69>, 0xf7fa7261, 0x7ffff7ecf980 <log_closure+80>, 0x555555e3d760, 0x7ffff7ecd803 <serialize_closure+131>, 0x7ffff7f7c310, 0x3cfb0, 0x555556081c20, 0x555556277560, 0x562f6075, 0x6519a6cbaf8b6400}
        ffi_args = {0x7fffffffdf20, 0x7fffffffdf28, 0x5555562bde58, 0x5555561c47f0, 0x5555561c47f8, 0x5555561c4800, 0xf7fa7375, 0x6519a6cbaf8b6400, 0x555556277560, 0x7ffff7ecf980 <log_closure+80>, 0x555555e8b9c0, 0x555555576440, 0x7ffff7e23a00 <main_arena>, 0xd8, 0x5555562f6050, 0x0, 0x5555562bde40, 
          0x7ffff7cef741 <__libc_calloc+129>, 0x7ffff7ecdd00 <wl_closure_send>, 0x7ffff7eda430 <wl_surface_requests+144>, 0x7ffff7ed45ee, 0x80006}
        implementation = <optimized out>
#8  0x00007ffff7ed22dc in wl_client_connection_data (fd=<optimized out>, mask=<optimized out>, data=<optimized out>) at ../src/wayland-server.c:437
        client = <optimized out>
        connection = 0x5555562c4fb0
        resource = <optimized out>
        object = 0x5555561c8b80
        closure = 0x5555560c91d0
        message = 0x7ffff7eda430 <wl_surface_requests+144>
        p = {3, 524294}
        resource_flags = 0
        opcode = 6
        size = <optimized out>
        since = <optimized out>
        len = <optimized out>
#9  0x00007ffff7ed0e22 in wl_event_loop_dispatch (loop=0x555555576530, timeout=timeout@entry=-1) at ../src/event-loop.c:1027
        ep = {{events = 1, data = {ptr = 0x55555556be30, fd = 1431748144, u32 = 1431748144, u64 = 93824992329264}}, {events = 1, data = {ptr = 0x555555e5bbe0, fd = 1441119200, u32 = 1441119200, u64 = 93825001700320}}, {events = 2945147904, data = {ptr = 0x55556519a6cb, fd = 1696179915, u32 = 1696179915, 
              u64 = 93825256761035}}, {events = 0, data = {ptr = 0x5555562c4fb0, fd = 1445744560, u32 = 1445744560, u64 = 93825006325680}}, {events = 4294960000, data = {ptr = 0xc00007fff, fd = 32767, u32 = 32767, u64 = 51539640319}}, {events = 0, data = {ptr = 0x5555562c7fc8, fd = 1445756872, u32 = 1445756872, 
              u64 = 93825006337992}}, {events = 1445748664, data = {ptr = 0x100005555, fd = 21845, u32 = 21845, u64 = 4294989141}}, {events = 0, data = {ptr = 0x7ffff7ecdadf <wl_connection_flush+319>, fd = -135472417, u32 = 4159494879, u64 = 140737352882911}}, {events = 1065353216, data = {ptr = 0xc00000000, fd = 0, 
              u32 = 0, u64 = 51539607552}}, {events = 0, data = {ptr = 0x7fffffffe3c0, fd = -7232, u32 = 4294960064, u64 = 140737488348096}}, {events = 1443357296, data = {ptr = 0xa0c, fd = 2572, u32 = 2572, u64 = 2572}}, {events = 0, data = {ptr = 0x0, fd = 0, u32 = 0, u64 = 0}}, {events = 4294960064, data = {
              ptr = 0x100007fff, fd = 32767, u32 = 32767, u64 = 4295000063}}, {events = 0, data = {ptr = 0x0, fd = 0, u32 = 0, u64 = 0}}, {events = 0, data = {ptr = 0x0, fd = 0, u32 = 0, u64 = 0}}, {events = 0, data = {ptr = 0x0, fd = 0, u32 = 0, u64 = 0}}, {events = 1445751236, data = {ptr = 0xc00005555, fd = 21845, 
              u32 = 21845, u64 = 51539629397}}, {events = 0, data = {ptr = 0x5555562bfbb8, fd = 1445723064, u32 = 1445723064, u64 = 93825006304184}}, {events = 4, data = {ptr = 0x1400000000, fd = 0, u32 = 0, u64 = 85899345920}}, {events = 0, data = {ptr = 0x100000001, fd = 1, u32 = 1, u64 = 4294967297}}, {
            events = 73, data = {ptr = 0x0, fd = 0, u32 = 0, u64 = 0}}, {events = 96, data = {ptr = 0x7ffff7bf74f0, fd = -138447632, u32 = 4156519664, u64 = 140737349907696}}, {events = 1443108192, data = {ptr = 0x56170f1000005555, fd = 21845, u32 = 21845, u64 = 6203443573120062805}}, {events = 21845, data = {
              ptr = 0x60, fd = 96, u32 = 96, u64 = 96}}, {events = 24, data = {ptr = 0x1800000000, fd = 0, u32 = 0, u64 = 103079215104}}, {events = 0, data = {ptr = 0x4, fd = 4, u32 = 4, u64 = 4}}, {events = 4160008759, data = {ptr = 0x400007fff, fd = 32767, u32 = 32767, u64 = 17179901951}}, {events = 0, data = {
              ptr = 0x555556041560, fd = 1443108192, u32 = 1443108192, u64 = 93825003689312}}, {events = 1440820288, data = {ptr = 0x3f80000000005555, fd = 21845, u32 = 21845, u64 = 4575657221408445781}}, {events = 16809983, data = {ptr = 0x4059000000000000, fd = 0, u32 = 0, u64 = 4636737291354636288}}, {
            events = 2945147904, data = {ptr = 0x55e042c06519a6cb, fd = 1696179915, u32 = 1696179915, u64 = 6188019282104395467}}, {events = 21845, data = {ptr = 0x555555576468, fd = 1431790696, u32 = 1431790696, u64 = 93824992371816}}}
        source = <optimized out>
        i = 1
        count = <optimized out>
        has_timers = <optimized out>
#10 0x00007ffff7ed1575 in wl_display_run (display=0x555555576440) at ../src/wayland-server.c:1431
No locals.
#11 0x000055555555fa02 in main ()

@sevz17
Copy link
Collaborator

sevz17 commented Oct 11, 2022

The problem is in the third frame, it says that the node is enabled (it should be disabled in unmaplayersurfacenotify()) and then try to schedule a frame for the output, maybe this will help:

diff --git a/dwl.c b/dwl.c
index 29c9eea..198f6e2 100644
--- a/dwl.c
+++ b/dwl.c
@@ -762,8 +762,16 @@ void
 cleanupmon(struct wl_listener *listener, void *data)
 {
 	Monitor *m = wl_container_of(listener, m, destroy);
+	LayerSurface *l, *tmp;
 	int nmons, i = 0;
 
+	for (i = 0; i <= ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY; i++) {
+		wl_list_for_each_safe(l, tmp, &m->layers[i], link) {
+			wlr_scene_node_set_enabled(l->scene, 0);
+			wlr_layer_surface_v1_destroy(l->layer_surface);
+		}
+	}
+
 	wl_list_remove(&m->destroy.link);
 	wl_list_remove(&m->frame.link);
 	wl_list_remove(&m->link);
@@ -771,7 +779,7 @@ cleanupmon(struct wl_listener *listener, void *data)
 	wlr_output_layout_remove(output_layout, m->wlr_output);
 	wlr_scene_output_destroy(m->scene_output);
 
-	if ((nmons = wl_list_length(&mons)))
+	if (!(i = 0) && (nmons = wl_list_length(&mons)))
 		do /* don't switch to disabled mons */
 			selmon = wl_container_of(mons.prev, selmon, link);
 		while (!selmon->wlr_output->enabled && i++ < nmons);

@BenJarg
Copy link
Contributor Author

BenJarg commented Oct 11, 2022

@sevz17 This fixes it! No segfault finally. The instance of yambar on the external monitor is still there when I re-plug in the monitor, but now it keeps its exclusion zone. I'm not sure if this is intended behavior, but it's smoother than when I tried the upstream of wlroots on wlroots-next.

@sevz17 sevz17 closed this as completed in 4eabf6f Oct 11, 2022
@sevz17
Copy link
Collaborator

sevz17 commented Oct 11, 2022

Many thanks for your help!

The instance of yambar on the external monitor is still there when I re-plug in the monitor, but now it keeps its exclusion zone. I'm not sure if this is intended behavior

I think it's because yambar creates another layer surface when the monitor is re-plug in, in any case it is ok

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
A: bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants