core: fix freeze when a monitor is DPMS-off during lock#1001
Conversation
|
Thanks a lot this is nice. Only thing really is that i think setting the swap interval once should be enough. Since the setting is bound to the surface, according to the docs, maybe call it in configure? |
b2901af to
003210a
Compare
|
Thanks for the review! I made the requested change. I tested on my setup and it still works as expected. Please let me know if you'd like to make any other changes or test anything else in particular! |
|
But does it actually fix what you described? |
|
generally this makes sense but I see three unrelated changes lole |
|
Thanks for the comments. I was experiencing two separate issues: one with the lock screen freezing while loading and another with the screen freezing after successfully entering my password. I'll get a video recorded to demo the fix, but it might take me a couple of days. |
With the default swap interval of 1, eglSwapBuffers blocks until the compositor sends wl_buffer.release. When a monitor is DPMS-off, the compositor never releases the buffer, stalling the main thread indefinitely. This prevents authentication from completing and leaves the lock screen frozen. Set the swap interval to 0 on each new EGL surface so swaps are non-blocking. Frame pacing is already controlled by wl_surface.frame callbacks, so this does not cause unbounded rendering. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
003210a to
9b5bf2d
Compare
|
Ok, so I spent a bit more time on this today and tracked the actual fix down to just the @PointerDilemma I know you said you messed with Here are a couple of recordings. I apologize in advance for the quality. You can see in the first that the screen freezes while transitioning to the lock screen. I click on the shadow of the password entry box, enter my password, powercycle the monitor, and hyprlock then exits successfully. Here's a video after the fix: I just enter my password and the screen unlocks as usual. |
|
Thanks! Generally this is OK usage of AI, but I wanted to rewrite the comment, because nobody actually researched if the #1015 |
|
@PointerDilemma I totally understand. I debated contributing "vibe-coded" changes at all in a domain in which I have limited understanding, but I noticed there were several related issues. I'm just happy you were able to find value in the contribution. |


Summary
Fix hyprlock freezing indefinitely when one monitor is DPMS-off at lock time, by preventing eglSwapBuffers from blocking on a compositor that will never release the buffer for a powered-off display.
Caveat: most of the work here was done by Claude. I am a developer, but I haven't done any C++ in ~15 years and don't have a good understanding of the internal workings of hyprland or display servers, etc. in general. However, I noticed there have been a lot of related issues posted, so I thought I would put this up for review by the maintainers. I'm happy to help further.
Problem
This seems possibly related to #953, #695, and maybe others. I have an NVidia RTX 3060Ti, a Samsung G9 (ultrawide) monitor, and an older 24" Samsung monitor. I'm currently using the nvidia-open drivers (595.58.03) on nixos.
The exact behavior I was seeing:
I tried setting
screencopy_mode = 1to see if that had any effect, but it did not.Solution
Egl.cpp — Call eglSwapInterval(0) in
configure. This makes the swap non-blocking: the buffer is committed to the compositor and the call returns immediately. Rendering rate is already properly throttled by wl_surface.frame callbacks, so this does not cause over-rendering.LockSurface.cpp — When configure() acknowledges a new serial, reset any pending frame callback before calling render(). This ensures every ack_configure is followed by a committed frame, breaking the protocol deadlock during rapid output reconfiguration.hyprlock.cpp — Skip zwp_linux_dmabuf_v1 binding when screencopy_mode=1. The GBM device created in the dmabuf feedback callback is only needed for DMABUF screencopy; creating it unnecessarily can block on the DRM render node under the same adverse conditions.Output.cpp — Guard createSessionLockSurface() with m_bTerminate to prevent a segfault when an output reconnects during session unlock teardown (the session lock object is already destroyed at that point).Test steps
No segfault when a monitor reconnects during unlockscreencopy_mode = 1 no longer attempts dmabuf setupDefault DMABUF screencopy mode still works when monitors are active🤖 Generated with Claude Code