From b0ecb645a1527ebeb6f3470d814763ad9ff64b22 Mon Sep 17 00:00:00 2001 From: Tyler Harms Date: Tue, 28 Jul 2026 15:49:39 -0500 Subject: [PATCH] Run cppcheck off the ReadAction thread --- .../cppcheck/CppCheckInspectionImpl.java | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/com/github/johnthagen/cppcheck/CppCheckInspectionImpl.java b/src/com/github/johnthagen/cppcheck/CppCheckInspectionImpl.java index 4b2965c..84a8bd4 100644 --- a/src/com/github/johnthagen/cppcheck/CppCheckInspectionImpl.java +++ b/src/com/github/johnthagen/cppcheck/CppCheckInspectionImpl.java @@ -8,11 +8,13 @@ import com.intellij.execution.process.CapturingProcessHandler; import com.intellij.execution.process.ProcessOutput; import com.intellij.notification.NotificationType; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Document; import com.intellij.openapi.progress.EmptyProgressIndicator; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.progress.util.ProgressIndicatorUtils; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiFile; @@ -33,6 +35,7 @@ import java.io.StringReader; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.Future; class CppCheckInspectionImpl { CppCheckInspectionImpl(final int verboseLevel) { @@ -283,9 +286,20 @@ public String executeCommandOnFile(@NotNull final VirtualFile vFile, final CapturingProcessHandler processHandler = new CapturingProcessHandler(cmd); final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator(); - final ProcessOutput output = processHandler.runProcessWithProgressIndicator( - indicator != null ? indicator : new EmptyProgressIndicator(), - TIMEOUT_MS); + // The platform forbids blocking subprocess waitFor() calls from a ReadAction thread + // (LocalInspectionTool.checkFile runs under one). Run the subprocess on a pooled thread + // and await it via ProgressIndicatorUtils so outer cancellation is still honored. + final ProgressIndicator effectiveIndicator = indicator != null ? indicator : new EmptyProgressIndicator(); + final Future future = ApplicationManager.getApplication().executeOnPooledThread( + () -> processHandler.runProcessWithProgressIndicator(effectiveIndicator, TIMEOUT_MS)); + final ProcessOutput output; + try { + output = ProgressIndicatorUtils.awaitWithCheckCanceled(future); + } catch (final ProcessCanceledException e) { + future.cancel(true); + processHandler.destroyProcess(); + throw e; + } if (output.isCancelled()) { throw new ProcessCanceledException();