driverkit: fast stuck-key recovery after VHID daemon reconnect (MAL-57 Layer 2)#26
Merged
Merged
Conversation
…7 Layer 2) When the socket to the Karabiner VHID daemon dies mid-keystroke (CPU starvation, daemon restart), a key Release lost in transit leaves the DriverKit virtual keyboard holding that key down. The daemon only garbage-collects the dead client after its own heartbeat timeout, so the key autorepeats at the OS level for 1-3 seconds (KeyPath MAL-57). Vendor karabiner-driverkit 0.3.1 (patch.crates-io) with three changes: 1. Stable per-PID client socket path. The daemon keys per-client state (including the virtual keyboard instance) by this path, so a reconnect reuses the existing keyboard instead of spawning a second instance while the stuck one repeats until GC. 2. virtual_hid_keyboard_reset on the keyboard-ready rising edge. Clears any stuck key as soon as the connection recovers; the next posted report re-asserts genuinely held keys since reports carry absolute full state. 3. Client server-check interval 3000ms -> 1000ms, matching the daemon's own per-client ping rate, so a dead connection is detected ~2s sooner. Also stops printing virtual_hid_keyboard_ready on every (~1/s) daemon status push - transitions only - which was 95%+ of the daemon stdout log volume. Worst-case stuck-key window drops from ~3s to ~1.5s; typical under 1s. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This was referenced Jun 11, 2026
malpern
added a commit
to malpern/KeyPath
that referenced
this pull request
Jun 11, 2026
…-57 Layer 2) Pulls malpern/kanata#26 into the bundled engine: stable per-PID VHID client socket path, virtual_hid_keyboard_reset on the keyboard-ready rising edge, and 1s (was 3s) daemon heartbeat detection. Worst-case stuck-key autorepeat after a daemon connection loss drops from ~3s to ~1.5s, typical under 1s. Also reduces daemon stdout log volume ~95% (ready-status now logged on transitions only). Engine release build (cmd,tcp_server, aarch64) verified locally via Scripts/build-kanata.sh: signs and passes binary smoke test. Co-Authored-By: Claude Fable 5 <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.
Summary
When the socket to the Karabiner VHID daemon dies mid-keystroke (CPU starvation under parallel builds, daemon restart), a key Release lost in transit leaves the DriverKit virtual keyboard holding that key down. The daemon only garbage-collects the dead client after its own heartbeat timeout, so the key autorepeats at the OS level for 1-3 seconds. Two live incidents on 2026-06-10 were traced end to end — see KeyPath
docs/bugs/MAL-57-duplicate-keypresses.md(2026-06-10 Incident Evidence) and KeyPath PR malpern/KeyPath#882 (Layer 1, launchd priority fix).Changes
Vendors
karabiner-driverkit0.3.1 intodriverkit/via[patch.crates-io]with three targeted changes:virtual_hid_device_service/client.hpp). The daemon keys per-client state — including the DriverKit virtual keyboard instance — by this path. A reconnect under the same path reuses the existing keyboard instead of spawning a second instance while the stuck one repeats until GC.local_datagram::client_implalready removes an existing file before bind, so stale files are harmless.virtual_hid_keyboard_reseton the keyboard-ready rising edge (c_src/driverkit.cpp). Clears any stuck key as soon as the connection recovers. Safe for held keys: kanata's next posted report carries absolute full state (the C++ report object tracks all pressed keys), so genuinely-held keys are re-asserted by the next event.Also:
virtual_hid_keyboard_readyis now printed only on transitions instead of every ~1s daemon status push — this was 95%+ of the 183MB daemon stdout log.Worst-case stuck-key window drops from ~3s to ~1.5s; typical under 1s. No Rust-side changes;
cargo buildandcargo checkpass with the patched crate resolving fromdriverkit/.Test plan
cargo check/cargo buildgreen with the vendored patchvirtual_hid_keyboard_reset sent after ready transitionappears on reconnect; ready-spam gone