fix(mcp): release RLock before transport call in MCPToolAdapter #10764

Merged
HAL9000 merged 8 commits from fix/issue-10512-mcptooladapter-rlock into master 2026-05-05 09:55:29 +00:00

8 Commits

Author SHA1 Message Date
HAL9000 90b06e6308 fix(db): remove redundant a5_007 merge migration (m4_004 already merged into m8_002 on master)
CI / benchmark-publish (pull_request) Has been skipped
CI / helm (pull_request) Successful in 46s
CI / build (pull_request) Successful in 52s
CI / lint (pull_request) Successful in 1m2s
CI / benchmark-regression (pull_request) Failing after 1m9s
CI / quality (pull_request) Successful in 1m13s
CI / security (pull_request) Successful in 1m31s
CI / typecheck (pull_request) Successful in 1m36s
CI / push-validation (pull_request) Successful in 24s
CI / integration_tests (pull_request) Successful in 3m43s
CI / e2e_tests (pull_request) Successful in 4m29s
CI / unit_tests (pull_request) Successful in 4m42s
CI / docker (pull_request) Successful in 1m52s
CI / coverage (pull_request) Successful in 11m35s
CI / coverage (push) Blocked by required conditions
CI / docker (push) Blocked by required conditions
CI / push-validation (push) Waiting to run
CI / status-check (push) Blocked by required conditions
CI / benchmark-publish (push) Has started running
CI / benchmark-regression (push) Has been skipped
CI / unit_tests (push) Has started running
CI / integration_tests (push) Has started running
CI / e2e_tests (push) Has started running
CI / status-check (pull_request) Successful in 3s
CI / helm (push) Successful in 35s
CI / build (push) Successful in 55s
CI / lint (push) Successful in 1m5s
CI / quality (push) Successful in 1m17s
CI / typecheck (push) Successful in 1m36s
CI / security (push) Successful in 1m43s
2026-05-05 09:37:22 +00:00
HAL9000 beaeac165d fix(db): add merge migration to resolve multiple Alembic heads
m4_004_schema_parity_resource_decision_checkpoint was added to master
after this branch was created, creating a second Alembic head alongside
a5_006_action_invariants_unique_constraint. The CI unit_tests job runs
on the merge commit (PR branch + master), so both migration files are
present, causing create_template_db.py to fail with MultipleHeads.

Add a5_007_merge_m4_004_and_a5_006 no-op merge migration to resolve
the two heads into a single head.
2026-05-05 09:37:22 +00:00
HAL9000 2240a028c8 fix(tests): replace ThreadPoolExecutor with threading.Thread in RLock concurrency steps
ThreadPoolExecutor holds internal locks (e.g. _global_shutdown_lock) that
can be in a locked state after fork(). The behave-parallel runner uses
multiprocessing.Pool with the fork start method, so forked worker processes
inherit these locked states and deadlock when trying to create or shut down
a ThreadPoolExecutor.

Replace both concurrent step implementations with direct threading.Thread
usage, following the pattern established in context_tier_thread_safety_steps.py
and other step files throughout the codebase. This eliminates the fork+lock
deadlock while preserving the deterministic concurrency-counter approach for
proving the RLock is released during transport calls.
2026-05-05 09:37:22 +00:00
HAL9000 236499f086 fix(tests): replace timing-based concurrency assertions with deterministic counter approach 2026-05-05 09:37:22 +00:00
HAL9000 60671306ea fix(tests): fix format and reduce timing thresholds in RLock concurrency tests
Fixed ruff format violation (single quotes to double quotes) in step definitions file.  Reduced SlowMCPTransport delay from 0.3s to 0.15s and tightened the wall-clock assertion from 0.9s to 0.40s to improve CI reliability while still proving concurrent execution.

ISSUES CLOSED: #10512
2026-05-05 09:37:22 +00:00
HAL9000 79ecaea18f fix(tests): use getattr for time._original_sleep fallback in RLock concurrency tests 2026-05-05 09:37:22 +00:00
HAL9000 69b7cd3cb2 fix(mcp): release RLock before transport call in MCPToolAdapter
MCPToolAdapter.invoke() and discover_tools() held the RLock during the
entire transport.call(), blocking all concurrent operations on the adapter.

The fix splits both methods into three phases:
1. Acquire lock — validate connection state and inputs
2. Release lock — make the transport call without holding the lock
3. Re-acquire lock (discover_tools only) — update shared state

Added Behave BDD tests verifying:
- Concurrent invocations complete in parallel (wall-clock < serial time)
- Concurrent discoveries complete in parallel
- Lock is provably not held during transport calls (cross-thread check)
- Validation still occurs under lock before transport call
- Disconnected adapter still raises RuntimeError under lock

ISSUES CLOSED: #10512
2026-05-05 09:37:22 +00:00
HAL9000 908e53ea85 fix(mcp): release RLock before transport call in MCPToolAdapter
MCPToolAdapter.invoke() and discover_tools() held the RLock during the
entire transport.call(), blocking all concurrent operations on the adapter.

The fix splits both methods into three phases:
1. Acquire lock — validate connection state and inputs
2. Release lock — make the transport call without holding the lock
3. Re-acquire lock (discover_tools only) — update shared state

Added Behave BDD tests verifying:
- Concurrent invocations complete in parallel (wall-clock < serial time)
- Concurrent discoveries complete in parallel
- Lock is provably not held during transport calls (cross-thread check)
- Validation still occurs under lock before transport call
- Disconnected adapter still raises RuntimeError under lock

ISSUES CLOSED: #10512
2026-05-05 09:37:22 +00:00