Fix keybindings scanner hanging on Hyprland list getters - #11027
Open
Ta-noshii wants to merge 1 commit into
Open
Fix keybindings scanner hanging on Hyprland list getters#11027Ta-noshii wants to merge 1 commit into
Ta-noshii wants to merge 1 commit into
Conversation
The keybindings menu discovers Lua-only binds by running the user's hyprland.lua under a stub hl whose every lookup answered a truthy sentinel, so ipairs over hl.get_monitors(), hl.get_windows() or hl.get_workspaces() never reached nil. A valid config looping over any of them spun a lua at 100% CPU forever, and every SUPER + K added one. Stub the three list getters with real empty tables and make the sentinel answer nil for numeric keys, so iteration over a getter the stub does not name ends too. Time-box the scan, say so on stderr when it is cut off, run it once per menu, and refuse to cache a cut-off result so an incomplete menu is not served until the next binding change. Fixes omacom#7025 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
omarchy-menu-keybindingsdiscovers Lua-only binds by running~/.config/hypr/hyprland.luain a standaloneluaunder a stubhl. Every lookup the stub does not model answers a truthy sentinel that also answers every key with itself, so:ipairsstops at the firstnil, and the sentinel never produces one. The same holds forhl.get_monitors(),hl.get_workspaces(), and any other getter the stub does not name.pcallcannot help because nothing raises. The scan has no timeout, so everySUPER + Kstarts another scan and nothing reaps the previous one. On the machine this was found on, 11luaprocesses had each held a full core for about 82 minutes; the Hyprland config loaded a module that reconciles window state withipairs(hl.get_windows())at startup, which is fine against the real API.Isolated reproduction, no user config involved:
Fix
hl.get_monitors,hl.get_windowsandhl.get_workspacesare stubbed with functions returning fresh empty tables, next to the existingget_configstub, so#,ipairsandpairssee an empty compositor.__indexanswersnilfor numeric keys, soipairsover a getter the stub does not name (hl.get_loaded_plugins()came up in the issue) ends too. String keys still chain, and nothing in the scanner indexes the sentinel numerically.timeout -k 2 10(overridable withOMARCHY_KEYBINDINGS_SCAN_TIMEOUT), so a config the stub still cannot satisfy cannot outlive the menu.luainstalls noSIGTERMhandler, so the child goes away and nothing is left behind.output_binding_records_uncachednow fails when the scan did not finish, so the menu still opens with whathyprctl bindsreported but the next press scans again instead of serving an incomplete menu until the next binding change.Existing fallback behaviour is unchanged: a scan that finishes is cached exactly as before, and a broken
hyprctlstill refuses the cache.Validation
New
test/shell.d/keybindings-menu-lua-scan-test.shruns the real script against a stubbedhyprctland isolated fixture configs in a throwawayHOME, in its own session so a leftoverluais detectable:ipairsover all three getters, over an unnamed getter, a#-bounded numeric loop and awhile cursor do cursor = cursor.next endwalk all terminate, and twohl.bindcalls declared after them are still discovered (the chords merge onto one row, and acode:key is recovered).while hl.get_active_monitor() do endfixture is cut off within the bound, says so on stderr, leaves noluain the session, still renders Hyprland's binds, and leaves neither a records file nor akeybindings.XXXXXXtemp file in the cache.Results on this branch:
bash test/shell.d/keybindings-menu-lua-scan-test.sh: 6 ok in ~2 s.luaat 99% CPU behind, which is the reported failure.bash test/shell.d/keybindings-menu-test.sh: 15 ok.bash test/shell.d/bin-style-test.sh,./test/cli,bash -non both files,git diff --check: pass../test/shell: 233 of 237 files pass. The four failures (config,snapper,unowned-system-paths,locate) fail identically on unmodifiedquattroin this checkout: three need a siblingomarchy-pkgscheckout andlocate-test.shtrips on a non-UTF-8 local file.Relation to #7564 and #8876
Both open PRs make the sentinel answer
nilfor numeric keys, and #7564 addstimeout 10. This change keeps that mechanism and closes what they leave open:timeoutalone, a scan that is killed still produces a records file: the success test is only whetherhyprctl bindsreturned anything, so the incomplete result is promoted to the cache and every later press serves it, silently missing every bind declared after the cut-off, until the next binding change. Here the scanner's status feeds the cache decision.pcallcannot report an externally killed process, so withtimeoutalone nothing is printed even underDEBUG=1. Here the timeout is named on stderr, which reaches the journal when the menu is launched from a bind.get_configstub.hyprctl, in its own session, and asserts the cut-off leaves noluabehind and nothing in the cache.Fixes #7025
🤖 Generated with Claude Code