Skip to content
This repository has been archived by the owner on Nov 1, 2021. It is now read-only.

Crash on types/wlr_buffer.c:52: wlr_buffer_unlock: Assertion `buffer->n_locks > 0' failed #2941

Closed
zccrs opened this issue May 28, 2021 · 1 comment · Fixed by #2944
Closed
Labels

Comments

@zccrs
Copy link
Contributor

zccrs commented May 28, 2021

Steps:

  1. edit the tinywl/tinywl.c main function to:
    add a new line code: "wlr_backend_destroy(server.backend);"
	wl_display_run(server.wl_display);

        wlr_backend_destroy(server.backend);
        
	wl_display_destroy_clients(server.wl_display);
	wl_display_destroy(server.wl_display);
	return 0;
  1. run the tinywl
  2. open a wayland application
  3. press the "Alt+ESC" shortcut to quit the tinywl

the log:

00:00:00.000 [INFO] [backend/x11/backend.c:399] Creating X11 backend
00:00:00.211 [INFO] [render/egl.c:318] Using EGL 1.5
...........
00:00:00.216 [DEBUG] [render/allocator.c:30] Trying to create gbm allocator
00:00:00.218 [DEBUG] [GLES2] Shader Stats: SGPRS: 24 VGPRS: 28 Code Size: 116 LDS: 0 Scratch: 0 Max Waves: 0 Spilled SGPRs: 0 Spilled VGPRs: 0 PrivMem VGPRs: 0
00:00:00.218 [DEBUG] [GLES2] Shader Stats: SGPRS: 24 VGPRS: 28 Code Size: 124 LDS: 0 Scratch: 0 Max Waves: 0 Spilled SGPRs: 0 Spilled VGPRs: 0 PrivMem VGPRs: 0
00:00:00.219 [DEBUG] [GLES2] Shader Stats: SGPRS: 16 VGPRS: 8 Code Size: 132 LDS: 0 Scratch: 0 Max Waves: 10 Spilled SGPRs: 0 Spilled VGPRs: 0 PrivMem VGPRs: 0
00:00:00.219 [DEBUG] [GLES2] Shader Stats: SGPRS: 24 VGPRS: 8 Code Size: 152 LDS: 0 Scratch: 0 Max Waves: 10 Spilled SGPRs: 0 Spilled VGPRs: 0 PrivMem VGPRs: 0
00:00:00.219 [DEBUG] [GLES2] Shader Stats: SGPRS: 8 VGPRS: 28 Code Size: 44 LDS: 0 Scratch: 0 Max Waves: 0 Spilled SGPRs: 0 Spilled VGPRs: 0 PrivMem VGPRs: 0
00:00:00.219 [DEBUG] [render/gbm_allocator.c:196] Created GBM allocator with backend drm
00:00:00.219 [DEBUG] [GLES2] Shader Stats: SGPRS: 24 VGPRS: 28 Code Size: 120 LDS: 0 Scratch: 0 Max Waves: 0 Spilled SGPRs: 0 Spilled VGPRs: 0 PrivMem VGPRs: 0
00:00:00.219 [DEBUG] [render/gbm_allocator.c:199] Using DRM node /dev/dri/renderD128
00:00:00.226 [DEBUG] [xcursor/wlr_xcursor.c:243] Loaded cursor theme 'default' at size 24 (114 available cursors)
00:00:00.228 [INFO] [tinywl.c:965] Running Wayland compositor on WAYLAND_DISPLAY=wayland-0
00:00:00.228 [DEBUG] [render/swapchain.c:105] Allocating new swapchain buffer
00:00:00.229 [DEBUG] [render/gbm_allocator.c:127] Allocated 1024x768 GBM buffer (format 0x34325241, modifier 0xFFFFFFFFFFFFFF)
00:00:00.229 [DEBUG] [render/gles2/renderer.c:137] Created GL FBO for buffer 1024x768
00:00:00.231 [DEBUG] [GLES2] Shader Stats: SGPRS: 8 VGPRS: 28 Code Size: 48 LDS: 0 Scratch: 0 Max Waves: 9 Spilled SGPRs: 0 Spilled VGPRs: 0 PrivMem VGPRs: 0
00:00:00.231 [DEBUG] [GLES2] Shader Stats: SGPRS: 8 VGPRS: 28 Code Size: 20 LDS: 0 Scratch: 0 Max Waves: 0 Spilled SGPRs: 0 Spilled VGPRs: 0 PrivMem VGPRs: 0
00:00:00.231 [DEBUG] [GLES2] Shader Stats: SGPRS: 16 VGPRS: 8 Code Size: 88 LDS: 0 Scratch: 0 Max Waves: 10 Spilled SGPRs: 0 Spilled VGPRs: 0 PrivMem VGPRs: 0
00:00:00.231 [DEBUG] [GLES2] Shader Stats: SGPRS: 24 VGPRS: 8 Code Size: 188 LDS: 0 Scratch: 0 Max Waves: 10 Spilled SGPRs: 0 Spilled VGPRs: 0 PrivMem VGPRs: 0
00:00:00.271 [DEBUG] [backend/x11/backend.c:757] Unhandled X11 event: ReparentNotify (21)
00:00:00.273 [DEBUG] [GLES2] Shader Stats: SGPRS: 24 VGPRS: 8 Code Size: 140 LDS: 0 Scratch: 0 Max Waves: 10 Spilled SGPRs: 0 Spilled VGPRs: 0 PrivMem VGPRs: 0
00:00:00.274 [DEBUG] [render/swapchain.c:105] Allocating new swapchain buffer
00:00:00.274 [DEBUG] [render/gbm_allocator.c:127] Allocated 32x32 GBM buffer (format 0x34325241, modifier 0xFFFFFFFFFFFFFF)
00:00:00.274 [DEBUG] [render/gles2/renderer.c:137] Created GL FBO for buffer 32x32
00:00:08.214 [DEBUG] [types/wlr_surface.c:723] New wlr_surface 0x555555e1ba30 (res 0x555555e79ca0)
00:00:08.214 [DEBUG] [types/wlr_surface.c:723] New wlr_surface 0x555555e1ba30 (res 0x555555e79ca0)
00:00:08.214 [DEBUG] [types/xdg_shell/wlr_xdg_surface.c:465] new xdg_surface 0x555555e13c70 (res 0x555555e125c0)
00:00:08.244 [DEBUG] [types/wlr_surface.c:723] New wlr_surface 0x555555e80380 (res 0x555555ef7ce0)
00:00:08.244 [DEBUG] [types/wlr_surface.c:723] New wlr_surface 0x555555e80380 (res 0x555555ef7ce0)
tinywl: types/wlr_buffer.c:52: wlr_buffer_unlock: Assertion `buffer->n_locks > 0' failed.
[1]    866728 abort (core dumped)  LC_ALL=C LD_PRELOAD=/usr/local/lib/libwlroots.so.9 ./tinywl
@emersion emersion added the bug label May 28, 2021
@zccrs
Copy link
Contributor Author

zccrs commented May 28, 2021

I recorded the function call stack of this buffer when unlock was called the last two times.

The first:

image

Second(crash):

image

zccrs added a commit to zccrs/wlroots that referenced this issue May 28, 2021
In the wlr_buffer_unlock, when the dropped of buffer is false and the
n_locks is 0 that not call the buffer_consider_destroy. After that, if
wlr_buffer_unlock is called again, "assert(buffer->n_locks> 0)" will
fail.

Fixes: swaywm#2941
zccrs added a commit to zccrs/wlroots that referenced this issue May 29, 2021
In the wlr_buffer_unlock, when the dropped of buffer is false and the
n_locks is 0 that not call the buffer_consider_destroy. So in the
gles2_texture_unref, should be check the buffer released state on call
wlr_buffer_unlock before.

Fixes: swaywm#2941
emersion added a commit to emersion/wlroots that referenced this issue May 29, 2021
When importing a DMA-BUF wlr_buffer as a wlr_texture, the GLES2
renderer caches the result, in case the buffer is used for texturing
again in the future. When the wlr_texture is destroyed by the caller,
the wlr_buffer is unref'ed, but the wlr_gles2_texture is kept around.
This is fine because wlr_gles2_texture listens for wlr_buffer's destroy
event to avoid any use-after-free.

However, with this logic wlr_texture_destroy doesn't "really" destroy
the wlr_gles2_texture. It just decrements the wlr_buffer ref'count.
Each wlr_texture_destroy call must have a matching prior
wlr_texture_create_from_buffer call or the ref'counting will go south.

Wehn destroying the renderer, we don't want to decrement any wlr_buffer
ref'count. Instead, we want to go through any cached wlr_gles2_texture
and destroy our GL state. So instead of calling wlr_texture_destroy, we
need to call our internal gles2_texture_destroy function.

Closes: swaywm#2941
bl4ckb0ne pushed a commit that referenced this issue May 30, 2021
When importing a DMA-BUF wlr_buffer as a wlr_texture, the GLES2
renderer caches the result, in case the buffer is used for texturing
again in the future. When the wlr_texture is destroyed by the caller,
the wlr_buffer is unref'ed, but the wlr_gles2_texture is kept around.
This is fine because wlr_gles2_texture listens for wlr_buffer's destroy
event to avoid any use-after-free.

However, with this logic wlr_texture_destroy doesn't "really" destroy
the wlr_gles2_texture. It just decrements the wlr_buffer ref'count.
Each wlr_texture_destroy call must have a matching prior
wlr_texture_create_from_buffer call or the ref'counting will go south.

Wehn destroying the renderer, we don't want to decrement any wlr_buffer
ref'count. Instead, we want to go through any cached wlr_gles2_texture
and destroy our GL state. So instead of calling wlr_texture_destroy, we
need to call our internal gles2_texture_destroy function.

Closes: #2941
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Development

Successfully merging a pull request may close this issue.

2 participants