Runnable (@NotNull ProcessHandler processHandler, @NotNull ExecutionMode mode, final @NotNull String presentableCmdline) { ProcessOutput outputCollected = new ProcessOutput(); processHandler.addProcessListener(new ProcessAdapter() { @Override public void onTextAvailable(@NotNull ProcessEvent event, @NotNull Key outputType) { String eventText = event.getText(); if (StringUtil.isNotEmpty(eventText)) { if (ProcessOutputType.isStdout(outputType)) { outputCollected.appendStdout(eventText); } else if (ProcessOutputType.isStderr(outputType)) { outputCollected.appendStderr(eventText); } } } }); Throwable invocatorStack = new Throwable(); return new Runnable() { private final Semaphore mySemaphore = new Semaphore(); private final Runnable myProcessRunnable = () -> { try { final boolean finished = processHandler.waitFor(1000L * mode.getTimeout()); if (!finished) { mode.onTimeout(processHandler, presentableCmdline, outputCollected, invocatorStack); processHandler.destroyProcess(); } } finally { mySemaphore.up(); } }; @Override public void run() { mySemaphore.down(); ApplicationManager.getApplication().executeOnPooledThread(myProcessRunnable); OSProcessHandler.checkEdtAndReadAction(processHandler); mySemaphore.waitFor(); } }; }