リファクタ #183
完了RuntimeTaskManagerTest.shutdownInterruptsAndWaitsForTrackedTask が flaky
説明
概要¶
RuntimeTaskManagerTest.shutdownInterruptsAndWaitsForTrackedTask() が CI 上でまれに失敗する(flaky)。プロダクションコードの不具合ではなく、テストコードのレースが原因。
失敗内容¶
org.opentest4j.AssertionFailedError: expected: <true> but was: <false>
at RuntimeTaskManagerTest.shutdownInterruptsAndWaitsForTrackedTask(RuntimeTaskManagerTest.java:38)
38 行目の assertTrue(interrupted.await(1, TimeUnit.SECONDS)) が false を返す。
原因¶
ワーカースレッドの処理が以下の形になっている:
started.countDown();
try {
while (!Thread.currentThread().isInterrupted()) {
Thread.sleep(1000);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
interrupted.countDown();
}
started.countDown() の後・Thread.sleep(1000) に入る前に manager.shutdown() が thread.interrupt() を撃つと、while (!isInterrupted()) が即 false になりループ本体に入らないため Thread.sleep() が一度も呼ばれず、InterruptedException が発生しない。結果 catch 節が走らず interrupted ラッチが down せず await が失敗する。CI のように CPU が逼迫した環境で発生しやすい。
修正方針¶
ループ条件を外して必ず Thread.sleep を通す。Thread.sleep は割り込みフラグが立った状態で呼ばれると即座に InterruptedException を投げるため、レースが解消する:
try {
while (true) {
Thread.sleep(1000);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
interrupted.countDown();
}
対象¶
src/test/java/bms/player/beatoraja/runtime/RuntimeTaskManagerTest.java
プロダクションコード(RuntimeTaskManager)の変更は不要。もう一方の startVirtualTracksAndInterruptsVirtualThread は直接 Thread.sleep を呼ぶため影響を受けない。
エージェント ちゃん さんが23日前に更新
- ステータス を 未着手 から 実装中 に変更
- 進捗率 を 0 から 10 に変更
実装に着手しました。
- ブランチ:
codex/fix-flaky-runtime-task-test - 対応方針: ワーカースレッドのループ条件
while (!isInterrupted())をwhile (true)に変更し、必ずThread.sleepを通すことで割り込みラッチのレースを解消する。
エージェント ちゃん さんが23日前に更新
- ステータス を 実装中 から 完了 に変更
- 進捗率 を 10 から 100 に変更
対応が完了しました。
概要¶
RuntimeTaskManagerTest.shutdownInterruptsAndWaitsForTrackedTask() の flaky を解消した。テストコードのレースが原因で、プロダクションコードの不具合ではない。
変更点¶
- ワーカースレッドのループを
while (!Thread.currentThread().isInterrupted())からwhile (true)に変更。割り込みフラグが立った状態でも必ずThread.sleepを通し、InterruptedException経由で catch 節が確実に走るようにした。 - 変更ファイル:
src/test/java/bms/player/beatoraja/runtime/RuntimeTaskManagerTest.java(1 行)。プロダクションコードは未変更。
テスト¶
-
xvfb-run -a ./gradlew test --tests 'bms.player.beatoraja.runtime.RuntimeTaskManagerTest' --rerun-tasks: 成功(2 tests, 0 failures)。連続 3 回実行でも安定。
関連 MR¶
- !19 (
codex/fix-flaky-runtime-task-test→ develop) マージ済み。