【要約】CancellationExceptionはなぜcatchしてはいけないのか [Qiita_Trend] | Summary by TechDistill
> Source: Qiita_Trend
Execute Primary Source
// Problem
開発者がsuspend関数内でThrowableやExceptionを広範にキャッチした際、コルーチンのキャンセル信号を握りつぶしてしまう問題。これにより、非同期タスクの制御が不能になる。具体的には以下の事象が発生する。
- ・whileループ内で例外を握りつぶすと、キャンセル検知後のdelayが即座に例外を投げ続け、制御不能な無限ループに陥る。
- ・キャンセル後も、suspension pointを経由しない後続の処理が実行され、不整合な状態が発生する。
- ・runCatchingの使用により、意図せずキャンセル信号を捕捉してしまう。
// Approach
開発者がキャンセル状態を正しく伝搬させるため、以下の3つの実装パターンを提案している。状況に応じて適切な手法を選択することで、キャンセル機構の整合性を保つ。
- ・CancellationExceptionを個別にキャッチし、そのままthrowして伝搬させる。
- ・coroutineContext.ensureActive()を呼び出し、キャンセル済みであれば例外を再送出する。
- ・while(isActive)を用い、ループの継続条件自体にキャンセル状態を組み込む。
// Result
開発者がキャンセル機構の仕組みを正しく理解し、適切な例外処理を選択できるようになる。これにより、非同期タスクのリークや、キャンセル失敗によるリソース消費の増大といった、実行時の致命的なバグを未然に防ぐことが可能となる。
Senior Engineer Insight
> 極めて実戦的な指摘だ。大規模なトラフィックを扱う現場では、キャンセル漏れによるリソースリークは、最終的にスレッド枯渇やメモリ圧迫を引き起こす。特に、便利なrunCatchingが罠になる点は、チーム全体のコーディング規約として周知すべきだ。また、個人の注意に頼らず、detekt等の静的解析やコンパイラプラグインによる自動検知を導入し、仕組みとして防ぐ姿勢が求められる。