mirror of
https://github.com/fusion44/blitz_api.git
synced 2026-08-13 11:52:45 +02:00
fix(api): catch subprocess timeouts in exec_bash_command
'from redis.asyncio import ... TimeoutError' shadowed the builtin TimeoutError. redis's TimeoutError is a RedisError subclass, not a builtin subclass, so the 'except TimeoutError' guarding asyncio.wait_for never matched: timed-out commands fell through to the generic handler, the child process was never terminated (leak), and the caller got a misleading 'unable to execute' error instead of a timeout. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
4355c8eabd
commit
ff54f93397
2 changed files with 26 additions and 1 deletions
|
|
@ -9,7 +9,9 @@ from typing import Any, Dict, Optional
|
|||
|
||||
from fastapi.encoders import jsonable_encoder
|
||||
from loguru import logger
|
||||
from redis.asyncio import Redis, TimeoutError
|
||||
# NB: do not import redis's TimeoutError here — it would shadow the builtin
|
||||
# and asyncio.wait_for's builtin TimeoutError would never be caught below.
|
||||
from redis.asyncio import Redis
|
||||
|
||||
from app.api.error_report.report import Report
|
||||
from app.api.models import ProcessResult
|
||||
|
|
|
|||
23
tests/test_exec_bash_timeout.py
Normal file
23
tests/test_exec_bash_timeout.py
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
"""
|
||||
Regression test: exec_bash_command must actually catch the timeout raised
|
||||
by asyncio.wait_for.
|
||||
|
||||
`from redis.asyncio import ... TimeoutError` used to shadow the builtin, so
|
||||
`except TimeoutError` never matched asyncio's builtin TimeoutError. Timed-out
|
||||
commands fell through to the generic handler, the child process was never
|
||||
terminated, and the caller got a misleading "unable to execute" error.
|
||||
"""
|
||||
|
||||
from app.api.utils import exec_bash_command
|
||||
from app.external.result_type.src.result.result import Err
|
||||
|
||||
|
||||
async def test_exec_bash_command_reports_timeout():
|
||||
# `bash -c 'sleep 5'` with a 0.5s budget must time out
|
||||
res = await exec_bash_command("-c 'sleep 5'", timeout=0.5)
|
||||
|
||||
assert isinstance(res, Err), "a timed-out command must return an Err"
|
||||
message = res.err_value.format_verbose().lower()
|
||||
assert "timed out" in message, (
|
||||
f"expected a timeout error, got: {message}"
|
||||
)
|
||||
Loading…
Add table
Add a link
Reference in a new issue