fix(cli): fall back to SelectSelector when kqueue can't watch stdin on macOS - #20948
Closed
outdoorsea wants to merge 1 commit into
Closed
fix(cli): fall back to SelectSelector when kqueue can't watch stdin on macOS#20948outdoorsea wants to merge 1 commit into
outdoorsea wants to merge 1 commit into
Conversation
On macOS with uv-managed cPython 3.11, the default kqueue selector cannot
register fd 0, so prompt_toolkit's loop.add_reader raises
OSError(EINVAL) ("[Errno 22] Invalid argument") from kqueue.control()
and the agent crashes immediately on startup (NousResearch#5884, also reported in
NousResearch#6393).
Probe KqueueSelector.register(0, EVENT_READ) before launching
prompt_toolkit. If it fails, install an event-loop policy that returns a
SelectorEventLoop backed by SelectSelector — select() works fine on
stdin in this Python build, so add_reader succeeds and the agent
launches normally.
Also extend the existing NousResearch#6393 fallback handler to recognize EINVAL /
EBADF / "Invalid argument" so that any future selector failure on stdin
shows the friendly "reinstall Python via pyenv or Homebrew" guidance
instead of an opaque traceback.
Verified on macOS (Darwin 24.6.0) with uv-managed cPython 3.11.15: the
kqueue probe fails, the policy switch fires, and `hermes` launches
cleanly. No effect on platforms where kqueue can register fd 0.
Collaborator
Contributor
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.
What does this PR do?
On macOS with uv-managed cPython 3.11, the default
kqueueselector cannot register fd 0, so whenprompt_toolkitcallsloop.add_reader(0, ...)duringapp.run(),kqueue.control()raisesOSError: [Errno 22] Invalid argument(EINVAL) and the agent crashes immediately on startup. Reproduces 100% on the affected Python builds.This PR fixes it by probing
KqueueSelector.register(0, EVENT_READ)once at startup; if it fails, an event-loop policy is installed that returns aSelectorEventLoopbacked bySelectSelectorinstead.select()works fine on stdin in this Python build, soadd_readersucceeds and the agent launches normally. Platforms where kqueue can register fd 0 are unaffected — the probe succeeds and the default policy is used.It also extends the existing #6393 fallback handler (which was added when this same family of bugs was first reported) to recognize EINVAL / EBADF /
"Invalid argument". Previously the handler only matched"is not registered"and"Bad file descriptor", so an EINVAL leaking through (which is the actual macOS+kqueue failure mode) re-raised as a raw traceback afterGoodbye! ⚕was printed — exactly the symptom in #5884.Related Issue
Fixes #5884
Re-fixes the underlying cause originally reported in #6393
Type of Change
Changes Made
cli.py— before launchingprompt_toolkit, probeKqueueSelector.register(0, ...)on macOS. On failure, install aDefaultEventLoopPolicysubclass whosenew_event_loop()returnsSelectorEventLoop(SelectSelector()).asyncio.run()(called insideapp.run()) then picks up the SelectSelector-backed loop andadd_readerworks.cli.py— extend the post-app.run()except (KeyError, OSError)handler to additionally matcherrno in (EINVAL, EBADF)and"Invalid argument"so the friendly "reinstall Python via pyenv or Homebrew" guidance is shown if any future selector failure on stdin slips past the probe.How to Test
Reproducing the original crash requires uv-managed cPython on macOS. With that build:
python -c "import selectors; kq = selectors.KqueueSelector(); kq.register(0, selectors.EVENT_READ)"— confirms the OS-level failure (OSError: [Errno 22] Invalid argument).hermescrashes with the traceback in [Setup]: OSError: [Errno 22] Invalid argument:[prompt_toolkit crash] #5884.hermeslaunches normally; piping/exitproduces clean shutdown.I verified all three on Darwin 24.6.0 with
cpython-3.11.15-macos-aarch64-none(the exact build affected in #5884). On Python builds where the kqueue probe passes (Homebrew, pyenv, system Python, Linux), the new code path is a no-op.Checklist
Code
fix(scope):,feat(scope):, etc.)pytest tests/ -qand all tests pass — did not run the full suite locally; please rely on CIDocumentation & Housekeeping
docs/, docstrings) — N/A (internal workaround, no user-facing surface change)cli-config.yaml.exampleif I added/changed config keys — N/ACONTRIBUTING.mdorAGENTS.mdif I changed architecture or workflows — N/Asys.platform == "darwin"and only triggers when kqueue actually fails to register fd 0; no effect on Linux/Windows or on macOS Pythons where kqueue works.