Skip to content

Fix(windows): dispatch hotkeys with a thread-safe function - #54

Merged
aleksandr-voitenko merged 6 commits into
streamlabsfrom
fix-electron43-windows-hotkey
Aug 21, 2026
Merged

Fix(windows): dispatch hotkeys with a thread-safe function#54
aleksandr-voitenko merged 6 commits into
streamlabsfrom
fix-electron43-windows-hotkey

Conversation

@aleksandr-voitenko

@aleksandr-voitenko aleksandr-voitenko commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator

Motivation and context

After upgrading Desktop from Electron 29 to Electron 43, pressing a registered global hotkey on Windows can crash the renderer. The Game Overlay hotkey provides a 100% reproducible path, although the problem affects Windows hotkeys generally and occurs before the JavaScript callback or Game Overlay logic executes.

The Windows polling thread currently invokes Napi::AsyncWorker::Queue() directly. This calls Node-API using a napi_env from an addon-created thread, which Node-API does not permit. Electron 43 exposes this undefined behavior as a crash in node::Environment::GetCurrent.

What changed

  • Replace per-callback AsyncWorker instances with a per-environment N-API thread-safe function.
  • Keep all JavaScript callback reference access on the JavaScript thread.
  • Associate native state with each Node environment, including worker_threads.
  • Use callback generations to discard events queued before a callback is unregistered or replaced.
  • Stop and join the polling thread before aborting the dispatcher during environment teardown.
  • Make hook shutdown atomic and allow the hook to restart safely.
  • Ensure queued native event data is released during normal and aborted teardown.
  • Leave the macOS implementation unchanged.

Testing

Added Windows tests that use SendInput to generate real F24 key presses rather than renderer-synthetic keyboard events. They cover:

  • Repeated callback delivery and ordering.
  • Callback unregistration.
  • Hook stop and restart.
  • Renderer teardown while the hook remains active.
  • Active worker_threads environment teardown.
  • Process survival and clean exit.

The test matrix runs the same N-API 4 addon binary under:

  • Electron 29.4.3
  • Electron 43.2.0

Compatibility

There are no JavaScript API changes. The implementation continues to target N-API 4, so the same binary remains compatible with the previous Electron 29 runtime as well as Electron 43.

After merging, a new native package release must be published and consumed by Desktop.

Replace AsyncWorker callbacks queued from the polling thread with a
per-environment N-API thread-safe function. Add safe teardown and
Electron 29/43 physical hotkey regression tests.
@aleksandr-voitenko aleksandr-voitenko changed the title [WIP] fix(windows): dispatch hotkeys with a thread-safe function Fix(windows): dispatch hotkeys with a thread-safe function Aug 20, 2026
@summeroff
summeroff requested a balanced review from Copilot August 20, 2026 23:50

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Reworks Windows hotkey dispatch to safely bridge the polling thread and JavaScript environments.

Changes:

  • Adds per-environment thread-safe callback dispatch and lifecycle cleanup.
  • Supports safe unregister, restart, worker teardown, and queued-event disposal.
  • Adds real Windows input tests across Electron 29 and 43.

Reviewed changes

Copilot reviewed 13 out of 14 changed files in this pull request and generated no comments.

Show a summary per file
File Description
source/hook-win.cpp Implements thread-safe Windows dispatch and cleanup.
source/module.cpp Connects per-environment state to exports.
source/hook.h Declares Windows initialization support.
test/send_input_win.cpp Generates real F24 input.
test/preload_hotkey_win.js Hosts renderer-side hook commands.
test/test_hotkey_win.js Tests callbacks, unregister, restart, and cleanup.
test/test_hotkey_teardown_win.js Tests active renderer teardown.
test/test_hotkey_worker_win.js Tests worker-environment teardown.
test/run_electron_test.js Runs and validates Electron tests.
.github/workflows/build.yml Adds Electron 29/43 Windows testing.
CMakeLists.txt Builds the input helper and updates CMake requirements.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@aleksandr-voitenko
aleksandr-voitenko merged commit 6de6854 into streamlabs Aug 21, 2026
16 checks passed
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