Conversation
ThreadPoolExecutor._adjust_thread_count is CPython-private and changed shape in 3.14 (initializer/initargs moved behind a new _create_worker_context indirection), so the subclass override here broke with `AttributeError: 'DaemonThreadPoolExecutor' object has no attribute '_initializer'` on every submit under 3.14 — which is how a stray 3.14 venv picked up by the Windows launcher self-heal turned into every tool call failing in the same session. Rebuilds the same daemon-worker behavior (never registered in concurrent.futures.thread._threads_queues, so the atexit join hook can't block interpreter exit on a wedged worker) directly on the public Executor ABC with only stable primitives, so a future CPython internals change can't break it again. Verified against the existing test suite plus manual checks for cancel_futures, initializer/initargs, exception propagation, and submit-after-shutdown, on both 3.13.12 and 3.14.4. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> (cherry picked from commit 2594c3e)
Contributor
96000 — fix(tools): rebuild DaemonThreadPoolExecutor on public Executor ABC — compatibility fix.
|
5 tasks
1 task
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
tools/daemon_pool.py'sDaemonThreadPoolExecutorsubclassedThreadPoolExecutorand mirrored its private_adjust_thread_countto get daemon workers (so a wedged tool call can't block interpreter exit — see the module's own docstring for the full rationale). CPython 3.14 restructured those private internals (__init__now stores a_create_worker_contextindirection instead of_initializer/_initargs), which breaks the override withAttributeError: 'DaemonThreadPoolExecutor' object has no attribute '_initializer'on every singlesubmit()call under 3.14.Concretely: any install that ends up running under a 3.14 interpreter (a stray venv, a future managed-runtime migration, etc.) gets every concurrent tool call failing at once, since all four call sites (
agent/conversation_compression.py,agent/memory_manager.py,agent/relay_runtime.py,agent/tool_executor.py) go through this class.Fix
Rebuilds the same daemon-worker behavior directly on the public
concurrent.futures.ExecutorABC using only stable primitives (threading,queue.SimpleQueue,weakref,concurrent.futures.Future) — no CPython-privateThreadPoolExecutorinternals at all, so a future internals change can't break it again. Same semantics preserved: workers are daemon threads never registered inconcurrent.futures.thread._threads_queues(so the atexit join hook can't block exit on a wedged worker), lazy idle-thread reuse,initializer/initargssupport, and the weakref-triggered auto-cleanup if a pool is dropped without an explicitshutdown().Test plan
tests/tools/test_daemon_pool.py) passes unchanged on 3.13.12cancel_futures=True,initializer/initargs, exception propagation throughFuture.result(), submit-after-shutdown()raisingRuntimeError, context-manager protocol