Make the keybindings menu's Lua bind scan safe against load-time config reads - #7564
Make the keybindings menu's Lua bind scan safe against load-time config reads#7564tobi wants to merge 1 commit into
Conversation
…ig reads omarchy-menu-keybindings learns about Lua-only binds by running the user's hyprland.lua under a stub `hl` whose every lookup answers a truthy noop table. That stub breaks as soon as a config reads compositor state at load time, which real configs do: - `for _, m in ipairs(hl.get_monitors())` never terminates, because noop[1], noop[2], ... are all non-nil. The menu exits, the `lua` child keeps spinning at 100% CPU under systemd --user until the next reboot. One such orphan ran for 27 hours on a laptop after a single SUPER+K. - `monitor.scale <= 0` (default/hypr/qconsole.lua:64) raises "attempt to compare table with number", which aborts the pcall'd scan, so every bind declared after that file is silently missing from the menu. The stub now answers nil for numeric indexes (so ipairs/`#` terminate), reports length 0, and degrades comparisons, arithmetic, and concatenation to harmless values instead of raising. The scan is also wrapped in `timeout 10` so a config the stub still cannot satisfy can never outlive the menu. Adds a shell test that scans a fixture config doing exactly those load-time reads; without the fix it hangs for the full timeout.
There was a problem hiding this comment.
Pull request overview
Hardens Lua keybinding discovery against hangs and load-time type errors.
Changes:
- Time-boxes Lua scanning to 10 seconds.
- Adds safer proxy metamethods.
- Adds regression coverage for loops, comparisons, and arithmetic.
Tip
If you aren't ready for review, convert to a draft PR.
Click "Convert to draft" or run gh pr ready --undo.
Click "Ready for review" or run gh pr ready to reengage.
Reviewed changes
Copilot reviewed 1 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
bin/omarchy-menu-keybindings |
Hardens and time-boxes Lua bind scanning. |
test/shell.d/menu-keybindings-lua-scan-test.sh |
Tests load-time reads and timeout configuration. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
Ran into this exact issue after upgrading to Quattro 4.0 Tested this fix locally; it resolves the infinite loop cleanly and makes the keybindings scan instantaneous. Hope to see this merged soon! |
Problem
omarchy-menu-keybindingslearns about Lua-only binds bydofile-ing the user'shyprland.luaunder a stubhlwhose every lookup returns a truthynooptable. Real configs read compositor state at load time, and the stub cannot survive that:Runaway
luaat 100 % CPU.for _, m in ipairs(hl.get_monitors())never terminates, becausenoop[1],noop[2], … are all non-nil. The menu exits, but theluachild keeps spinning undersystemd --useruntil reboot. Found one on my laptop that had run for 27 hours after a singleSUPER+K(PIDsomarchy-menu-keybindings→lua, 60 % of a core,dofile(hyprland.lua)never returned).Silently dropped binds. On current quattro,
default/hypr/qconsole.lua:64doesmonitor.scale <= 0, which under the stub raises attempt to compare table with number. The scan ispcall'd, so it just stops there — every Lua bind declared after thatrequireis missing from the menu (DEBUG=1showslua bind scan failed: …qconsole.lua:64).Fix
noop.__indexanswersnilfor numeric keys (soipairs/numeric loops end),__lenis 0, and__lt/__le, arithmetic,__concat,__tostringdegrade to harmless values instead of raising. String-key lookups behave as before.timeout 10so a config the stub still cannot satisfy can never outlive the menu.Test
test/shell.d/menu-keybindings-lua-scan-test.shextracts the embedded scan and runs it against a fixturehyprland.luathat iterates monitors, comparesmonitor.scale, does arithmetic/concatenation on stub fields, and then declares two binds. Without the fix it hangs for the full 10 s timeout and fails; with it the scan returns in milliseconds and both binds are reported. Also verified on my own config: the scan now completes with noscan failedand lists the Lua binds that were previously lost afterqconsole.lua.