fix(gateway): contain cron provider shutdown exits

This commit is contained in:
fangliquan 2026-08-12 20:34:46 +08:00 committed by kshitij
parent a7f0abc845
commit 64aaf56dbc
2 changed files with 24 additions and 4 deletions

View File

@ -27830,6 +27830,19 @@ def _start_cron_ticker(stop_event: threading.Event, adapters=None, loop=None, in
InProcessCronScheduler().start(stop_event, adapters=adapters, loop=loop, interval=interval)
def _stop_cron_provider(provider) -> None:
"""Stop a cron provider without letting it choose the gateway exit code."""
try:
provider.stop()
except SystemExit as exc:
logger.warning(
"Cron provider stop() attempted to exit the gateway with code %s; ignoring",
exc.code,
)
except Exception as exc:
logger.debug("Cron provider stop() error: %s", exc)
# Upper bound for cooperatively draining the cron ticker on shutdown. The cron
# thread delivers via ``safe_schedule_threadsafe`` and blocks on
# ``future.result(timeout=60)`` (see cron/scheduler.py::_deliver_result), so a
@ -28493,10 +28506,7 @@ async def start_gateway(config: Optional[GatewayConfig] = None, replace: bool =
# silently dropped (#58818). Awaiting keeps the loop alive so the in-flight
# delivery finishes before we tear down.
cron_stop.set()
try:
cron_provider.stop()
except Exception as e:
logger.debug("Cron provider stop() error: %s", e)
_stop_cron_provider(cron_provider)
if not await _await_thread_exit(cron_thread, timeout=_CRON_SHUTDOWN_DRAIN_TIMEOUT):
logger.warning(
"Cron ticker did not exit within %.0fs of shutdown — an in-flight "

View File

@ -49,6 +49,16 @@ def test_cleanup_agent_resources_reaps_stale_aux_clients():
cleanup_mock.assert_called_once()
def test_cron_provider_stop_cannot_override_gateway_exit_code(caplog):
provider = MagicMock()
provider.stop.side_effect = SystemExit(GATEWAY_SERVICE_RESTART_EXIT_CODE)
gateway_run._stop_cron_provider(provider)
provider.stop.assert_called_once_with()
assert "attempted to exit the gateway with code 75; ignoring" in caplog.text
@pytest.mark.asyncio
async def test_gateway_stop_interrupts_running_agents_and_cancels_adapter_tasks():
runner, adapter = make_restart_runner()