fix(agent): preserve external cancellation in message loop
Made-with: Cursor
This commit is contained in:
@@ -265,9 +265,9 @@ class AgentLoop:
|
|||||||
except asyncio.TimeoutError:
|
except asyncio.TimeoutError:
|
||||||
continue
|
continue
|
||||||
except asyncio.CancelledError:
|
except asyncio.CancelledError:
|
||||||
# anyio/MCP cancel scopes surface as CancelledError (a BaseException subclass).
|
# Preserve real task cancellation so shutdown can complete cleanly.
|
||||||
# Re-raise only if the loop itself is being shut down; otherwise keep running.
|
# Only ignore non-task CancelledError signals that may leak from integrations.
|
||||||
if not self._running:
|
if not self._running or asyncio.current_task().cancelling():
|
||||||
raise
|
raise
|
||||||
continue
|
continue
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
@@ -65,6 +65,18 @@ class TestRestartCommand:
|
|||||||
|
|
||||||
mock_handle.assert_called_once()
|
mock_handle.assert_called_once()
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_run_propagates_external_cancellation(self):
|
||||||
|
"""External task cancellation should not be swallowed by the inbound wait loop."""
|
||||||
|
loop, _bus = _make_loop()
|
||||||
|
|
||||||
|
run_task = asyncio.create_task(loop.run())
|
||||||
|
await asyncio.sleep(0.1)
|
||||||
|
run_task.cancel()
|
||||||
|
|
||||||
|
with pytest.raises(asyncio.CancelledError):
|
||||||
|
await asyncio.wait_for(run_task, timeout=1.0)
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_help_includes_restart(self):
|
async def test_help_includes_restart(self):
|
||||||
loop, bus = _make_loop()
|
loop, bus = _make_loop()
|
||||||
|
|||||||
Reference in New Issue
Block a user