Skip to content

core: fix freeze when a monitor is DPMS-off during lock#1001

Closed
tmbull wants to merge 1 commit into
hyprwm:mainfrom
tmbull:fix-samsung-g9-freezing
Closed

core: fix freeze when a monitor is DPMS-off during lock#1001
tmbull wants to merge 1 commit into
hyprwm:mainfrom
tmbull:fix-samsung-g9-freezing

Conversation

@tmbull

@tmbull tmbull commented Apr 28, 2026

Copy link
Copy Markdown
Contributor

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:

  • On transition to lock screen, the screen would freeze (I would see my session with a shadow of the lock screen over it).
  • I could enter my password (blindly), but the screen would still be frozen until I manually powercycled my monitor
  • After powercycling, the system would unlock
  • After the freezing issue was fixed, I also noticed that hyprlock would segfault on unlock, so that is addressed here as well.

I tried setting screencopy_mode = 1 to 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

  • Normal password unlock works without monitor power-cycle
  • Fade-in and fade-out animations play correctly on all monitors
  • Lock/unlock works with a monitor in DPMS-off state at lock time
  • No segfault when a monitor reconnects during unlock
  • screencopy_mode = 1 no longer attempts dmabuf setup
  • Default DMABUF screencopy mode still works when monitors are active

🤖 Generated with Claude Code

Comment thread src/core/Egl.cpp Outdated
Comment thread src/core/LockSurface.cpp Outdated
@PointerDilemma

Copy link
Copy Markdown
Collaborator

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?

@tmbull tmbull force-pushed the fix-samsung-g9-freezing branch from b2901af to 003210a Compare April 29, 2026 22:36
@tmbull

tmbull commented Apr 29, 2026

Copy link
Copy Markdown
Contributor Author

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!

@PointerDilemma

Copy link
Copy Markdown
Collaborator

But does it actually fix what you described?
I am a bit in doubt about that, since I experimented with eglSwapInterval Before and also with frame callback stuff.
Can you send some evidence like a recording maybe?

@vaxerski

vaxerski commented May 3, 2026

Copy link
Copy Markdown
Member

generally this makes sense but I see three unrelated changes lole

@tmbull

tmbull commented May 4, 2026

Copy link
Copy Markdown
Contributor Author

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>
@tmbull tmbull force-pushed the fix-samsung-g9-freezing branch from 003210a to 9b5bf2d Compare May 5, 2026 18:26
@tmbull

tmbull commented May 5, 2026

Copy link
Copy Markdown
Contributor Author

Ok, so I spent a bit more time on this today and tracked the actual fix down to just the eglSwapInterval change. The rest was just some hallucinating on the way to the actual solution.

@PointerDilemma I know you said you messed with eglSwapInterval previously, but maybe the issue I was experiencing is slightly different to the previously reported issue.

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.

hyprlock g9 broken

Here's a video after the fix:

hyprlock g9 fixed

I just enter my password and the screen unlocks as usual.

@PointerDilemma

Copy link
Copy Markdown
Collaborator

Thanks!

Generally this is OK usage of AI, but I wanted to rewrite the comment, because nobody actually researched if the wl_buffer.release event is actually the mechanism used by the egl wayland implementation to do vsync with eglSwapInterval.
I didn't really like the comment also because the point is just that when we manage frame callbacks ourselves, we don't want to use any sync mechanism that comes with EGL.

#1015
I added you as a co-author, but omitted claude.

@tmbull

tmbull commented May 14, 2026

Copy link
Copy Markdown
Contributor Author

@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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants