Replace all occurrences of `await asyncio.gather(..., return_exceptions=True)` without checking exceptions
- Dominant language
- Python
- Stars
- 670
- Forks
- 183
- Avg merge
- 15h 13m
- Merged PRs (30d)
- 368
Description
It **must** use `aiotools.as_completed_safe()` or similar structured primitives which lets the caller handle exceptions explicitly.
> 전체 코드베이스에서 await asyncio.gather(..., return_exceptions=True)의 리턴값을 사용하지 않고 버리거나 리턴값의 exception을 제대로 검사하지 않는 경우를 모두 전수조사해서 실제 코드 등장 지점과 함께 알려주세요.
```
🟥 범주 A-bug: 반환값 완전 폐기 — 실제 버그 또는 위험 신호
┌─────────────────────────────────────────────────────────────────────────────────┬─────────────────────────────────────────────────────────────────────────────┐
│ 위치 │ 문제 │
├─────────────────────────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────┤
│ src/ai/backend/manager/sokovan/scheduler/launcher/launcher.py:160 │ pull_tasks(에이전트별 이미지 pull) 결과를 버림. 이미지 pull 실패가 로깅조차 되지 않고 조용히 │
│ │ 삼켜짐. 하류 세션 start 실패 원인 추적 곤란. │
├─────────────────────────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────┤
│ src/ai/backend/storage/volumes/stats/observer.py:72 │ 볼륨 stats 관찰 태스크 결과를 버림. 관찰 실패 시 메트릭 공백이 진단 없이 발생. │
├─────────────────────────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────┤
│ src/ai/backend/agent/kubernetes/agent.py:1074, │ fetch_tasks(컨테이너 정보 수집) 결과를 버림. 각 태스크가 내부 dict에 side-effect로 채우는 │
│ src/ai/backend/agent/docker/agent.py:1662 │ 구조라 실패 컨테이너는 조용히 누락될 수 있음. │
├─────────────────────────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────┤
│ src/ai/backend/kernel/base.py:89 │ I/O 연산(로그 복사) gather를 bare await. write/multipart send 실패가 묻힘. │
└─────────────────────────────────────────────────────────────────────────────────┴─────────────────────────────────────────────────────────────────────────────┘
🟨 범주 A-gray: 반환값 폐기 — 의도적 정리 패턴으로 판단
취소(cancel) 후 정리, shutdown __aexit__, warmup 등은 예외를 일부러 삼키는 게 관례입니다. 리뷰 필요는 없지만 목록 남깁니다.
- scripts/monitor-session-events.py:62 — 취소된 메일 태스크 정리
- src/ai/backend/agent/kernel.py:826 — __aenter__ 실패 후 정리
- src/ai/backend/client/compat.py:36, src/ai/backend/kernel/compat.py:29 — 이벤트 루프 종료 시 전체 태스크 취소 (stdlib 패턴)
- src/ai/backend/common/asyncio.py:37 — cancel_tasks() 헬퍼 (취소 후 대기)
- src/ai/backend/common/events/dispatcher.py:389 — dispatcher shutdown 태스크 취소
- src/ai/backend/kernel/base.py:298 — 서비스 terminate_and_wait() shutdown 단계
- src/ai/backend/manager/registry.py:1759 — 에이전트별 태스크 집계
- src/ai/backend/manager/api/gql/graphql_ws/subscriptions.py:78 — cancel_all() 구독 정리
- src/ai/backend/manager/api/rest/events/handler.py:257 — __aexit__ 정리
- src/ai/backend/manager/api/rest/stream/handler.py:640, :724 — 스트림 취소 정리
- src/ai/backend/manager/event_dispatcher/handlers/stream_cleanup.py:48 — 스트림 정리 콜백
- src/ai/backend/manager/clients/storage_proxy/session_manager.py:141 — aclose() 세션 정리
- src/ai/backend/storage/watcher.py:39 — 취소된 태스크 정리
- src/ai/backend/storage/client/huggingface.py:485 — 메타데이터 다운로드 fire-and-forget
- plugins/backend.ai-accelerator-cuda-enterprise/benchmarks/ml/bench_endpoints.py:291, infer_vllm.py:307 — 벤치 warmup
🟧 범주 B: 반환값 대입했으나 검사 불완전
B-1. isinstance(x, Exception)만 검사해 BaseException(특히 CancelledError) 누락
Python 3.8+ 에서 asyncio.gather(return_exceptions=True)는 CancelledError를 결과 리스트에 담습니다. Exception으로 검사하면 누락됩니다. 이 중 일부는 의도된 것(사용자 비즈니스 로직 한정 탐지)일 수
있으나, 다수는 실수입니다.
┌──────────────────────────────────────────────────────────────┬─────────────────────────────────────────────────────────────────────────────────────┐
│ 위치 │ 비고 │
├──────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────┤
│ src/ai/backend/kernel/base.py:1188 │ intrinsic_spawn_coros — 서비스 spawn 실패 검사. CancelledError 누락 시 서비스 기동 실패가 묻힘. │
├──────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────┤
│ src/ai/backend/manager/services/user/service.py:262 │ 사용자 purge 결과 │
├──────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────┤
│ src/ai/backend/manager/services/user/service.py:335 │ 사용자 purge 결과 (유사 위치) │
├──────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────┤
│ src/ai/backend/manager/sokovan/scheduler/coordinator.py:1326 │ record_tasks 통계 기록 │
├──────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────┤
│ src/ai/backend/client/cli/session/execute.py:849 │ CLI executor — 다중 케이스 실행 결과 검사. CLI 종료용이므로 영향 낮음. │
└──────────────────────────────────────────────────────────────┴─────────────────────────────────────────────────────────────────────────────────────┘
B-2. gather 결과 주변에 의미 없는 try/except — 도달 불가 코드
┌────────────────────────────────────┬───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ 위치 │ 문제 │
├────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ src/ai/backend/agent/agent.py:1655 │ try: await gather(..., return_exceptions=True); except TimeoutError:. return_exceptions=True는 예외를 결과로 변환하므로 TimeoutError는 절대 raise되지 않음. │
│ │ 결과 리스트를 순회해서 TimeoutError 인스턴스를 찾아야 함. 현재 clean_kernel_objects() 내부 코루틴들은 wait_for로 감싸져 있지 않으므로 로그도 남지 않음. │
└────────────────────────────────────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
🟩 범주 C: 정상 처리 (isinstance(r, BaseException) 순회)
아래 43건은 모두 결과를 순회하며 BaseException 체크 후 로깅/재발생/수집함. 문제 없음.
- plugins/.../bench_endpoints.py:296, infer_vllm.py:315
- src/ai/backend/agent/stats.py:513, 751, 920
- src/ai/backend/agent/server.py:824 (pattern-match로 분리)
- src/ai/backend/agent/docker/intrinsic.py:838 (non-Exception BaseException은 re-raise)
- src/ai/backend/common/bgtask/bgtask.py:579
- src/ai/backend/common/clients/valkey_client/valkey_bgtask/client.py:357
- src/ai/backend/common/health_checker/probe.py:138, checkers/valkey.py:117
- src/ai/backend/manager/services/vfolder/services/vfolder.py:1229, 1289, 1355
- src/ai/backend/manager/services/notification/service.py:371
- src/ai/backend/manager/sokovan/scheduler/coordinator.py:299, 345, 404, 468, 987, 1433, 1457
- src/ai/backend/manager/clients/agent/pool.py:247 (내부 _check_one_health가 자체 try/except)
- src/ai/backend/manager/sokovan/scheduler/launcher/launcher.py:207, 422
- src/ai/backend/manager/sokovan/scheduler/terminator/terminator.py:122
- src/ai/backend/manager/sokovan/deployment/executor.py:385, 460, 717
- src/ai/backend/storage/api/manager.py:898
- src/ai/backend/appproxy/coordinator/health_checker.py:1042 (isinstance(r, (Exception, BaseException)))
- src/ai/backend/appproxy/worker/metrics.py:315
```
JIRA Issue: BA-5799
Contributor guide
Assessment
This issue has not been assessed yet.