Skip to content

fix(ext/napi): keep event loop alive while uv_async_t handle is active#32702

Merged
bartlomieju merged 2 commits intodenoland:mainfrom
bartlomieju:fix/uv-async-send-ref
Mar 14, 2026
Merged

fix(ext/napi): keep event loop alive while uv_async_t handle is active#32702
bartlomieju merged 2 commits intodenoland:mainfrom
bartlomieju:fix/uv-async-send-ref

Conversation

@bartlomieju
Copy link
Copy Markdown
Member

Summary

  • Add ref_op() in uv_async_init and unref_op() in uv_close to match libuv semantics where an active uv_async_t handle keeps the event loop alive until closed
  • Fix libuv_sys_lite::setup() to run on all platforms in the test NAPI module (was gated behind #[cfg(windows)])
  • Add test-napi subcommand to the ./x developer CLI
  • Add test verifying uv_async_init keeps the event loop alive without needing a threadsafe function workaround

Closes #32614

Test plan

  • New test "napi uv async keeps event loop alive" passes with fix
  • Same test fails on main (process exits before callback fires)
  • All existing NAPI tests pass (./x test-napi — 58 passed, 0 failed)

🤖 Generated with Claude Code

bartlomieju and others added 2 commits March 14, 2026 09:27
In libuv, `uv_async_init` starts the handle immediately and keeps the
event loop running until `uv_close` is called. Our polyfill was missing
this behavior — `uv_async_send` would spawn work to the main thread but
nothing kept the event loop alive, so callbacks could be silently dropped.

This adds `ref_op()` in `uv_async_init` and `unref_op()` in `uv_close`
to match real libuv semantics.

Also fixes `libuv_sys_lite::setup()` to run on all platforms in the test
NAPI module (was Windows-only), and adds a `test-napi` subcommand to
the `./x` developer CLI.

Closes denoland#32614

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
napi_sys::setup();
libuv_sys_lite::setup();
}
unsafe {
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Without this change the newly added tests were causing a panic.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Drive-by cleanup to avoid deprecation warnings

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Ditto

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Drive by helper because it always takes me 5m to figure out correct invocation and agents are no better

@bartlomieju bartlomieju changed the title fix(napi): keep event loop alive while uv_async_t handle is active fix(ext/napi): keep event loop alive while uv_async_t handle is active Mar 14, 2026
Copy link
Copy Markdown
Member

@littledivy littledivy left a comment

Choose a reason for hiding this comment

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

Reviewed the changes. No issues found.

@bartlomieju bartlomieju merged commit 7ab15ad into denoland:main Mar 14, 2026
113 checks passed
@bartlomieju bartlomieju deleted the fix/uv-async-send-ref branch March 14, 2026 13:55
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.

napi: uv_async_send doesn't keep event loop alive

2 participants