Skip to content

Commit 233bcf3

Browse files
aksOpsclaude
andcommitted
fix: add 30-second per-file timeout to prevent index from hanging
Future.get() in all three analysis paths (analyze, index batched, smart index) had no timeout — if an ANTLR parser or regex hangs on a pathological file, the entire batch blocks forever. Fix: Future.get(30, TimeUnit.SECONDS) with TimeoutException handler that cancels the stuck task, logs a warning, and continues with the next file. Affects Analyzer.java lines 300, 591, 961. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 654e920 commit 233bcf3

1 file changed

Lines changed: 12 additions & 3 deletions

File tree

src/main/java/io/github/randomcodespace/iq/analyzer/Analyzer.java

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,10 @@ private AnalysisResult runWithCache(Path root, Integer parallelism, AnalysisCach
297297
// Collect in order -- deterministic regardless of thread completion order
298298
for (int i = 0; i < futures.size(); i++) {
299299
try {
300-
futures.get(i).get();
300+
futures.get(i).get(30, java.util.concurrent.TimeUnit.SECONDS);
301+
} catch (java.util.concurrent.TimeoutException e) {
302+
futures.get(i).cancel(true);
303+
log.warn("Analysis timed out for {} (30s limit), skipping", files.get(i).path());
301304
} catch (ExecutionException e) {
302305
log.warn("Analysis failed for {}", files.get(i).path(), e.getCause());
303306
} catch (InterruptedException e) {
@@ -585,7 +588,10 @@ private AnalysisResult runBatchedWithCache(Path root, Integer parallelism, int b
585588
// Collect in order
586589
for (int i = 0; i < futures.size(); i++) {
587590
try {
588-
futures.get(i).get();
591+
futures.get(i).get(30, java.util.concurrent.TimeUnit.SECONDS);
592+
} catch (java.util.concurrent.TimeoutException e) {
593+
futures.get(i).cancel(true);
594+
log.warn("Analysis timed out for {} (30s limit), skipping", batch.get(i).path());
589595
} catch (ExecutionException e) {
590596
log.warn("Analysis failed for {}", batch.get(i).path(), e.getCause());
591597
} catch (InterruptedException e) {
@@ -952,7 +958,10 @@ private int[] processSmartBatch(
952958

953959
for (int i = 0; i < futures.size(); i++) {
954960
try {
955-
futures.get(i).get();
961+
futures.get(i).get(30, java.util.concurrent.TimeUnit.SECONDS);
962+
} catch (java.util.concurrent.TimeoutException e) {
963+
futures.get(i).cancel(true);
964+
log.warn("Analysis timed out for {} (30s limit), skipping", batch.get(i).path());
956965
} catch (ExecutionException e) {
957966
log.warn("Analysis failed for {}", batch.get(i).path(), e.getCause());
958967
} catch (InterruptedException e) {

0 commit comments

Comments
 (0)