From e2b843cc8f73d6cbeeb35d2f1de6ea35f842b688 Mon Sep 17 00:00:00 2001 From: David Thompson Date: Tue, 9 Sep 2025 11:33:25 -0400 Subject: [PATCH] Simplify `ParentProcessWatcher` See https://github.com/eclipse-lemminx/lemminx/pull/1753 Signed-off-by: David Thompson --- .../qute/ls/commons/ParentProcessWatcher.java | 61 +------------------ 1 file changed, 3 insertions(+), 58 deletions(-) diff --git a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/ls/commons/ParentProcessWatcher.java b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/ls/commons/ParentProcessWatcher.java index db1159a8b..1c570c0bb 100644 --- a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/ls/commons/ParentProcessWatcher.java +++ b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/ls/commons/ParentProcessWatcher.java @@ -13,20 +13,17 @@ *******************************************************************************/ package com.redhat.qute.ls.commons; -import java.io.IOException; +import java.util.Optional; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; import java.util.function.Function; -import java.util.logging.Level; import java.util.logging.Logger; import org.eclipse.lsp4j.jsonrpc.MessageConsumer; import org.eclipse.lsp4j.services.LanguageServer; -import com.google.common.io.Closeables; - /** * Watches the parent process PID and invokes exit if it is no longer available. * This implementation waits for periods of inactivity to start querying the @@ -35,8 +32,6 @@ public final class ParentProcessWatcher implements Runnable, Function { private static final Logger LOGGER = Logger.getLogger(ParentProcessWatcher.class.getName()); - private static final boolean isJava1x = System.getProperty("java.version").startsWith("1."); - private static final boolean isWindows = System.getProperty("os.name").toLowerCase().indexOf("win") >= 0; /** * Exit code returned when XML Language Server is forced to exit. @@ -86,58 +81,8 @@ private boolean parentProcessStillRunning() { if (pid == 0 || lastActivityTime > (System.currentTimeMillis() - INACTIVITY_DELAY_SECS)) { return true; } - String command; - if (isWindows) { - command = "cmd /c \"tasklist /FI \"PID eq " + pid + "\" | findstr " + pid + "\""; - } else { - command = "kill -0 " + pid; - } - Process process = null; - boolean finished = false; - try { - process = Runtime.getRuntime().exec(command); - finished = process.waitFor(POLL_DELAY_SECS, TimeUnit.SECONDS); - if (!finished) { - process.destroy(); - finished = process.waitFor(POLL_DELAY_SECS, TimeUnit.SECONDS); // wait for the process to stop - } - if (isWindows && finished && process.exitValue() > 1) { - // the tasklist command should return 0 (parent process exists) or 1 (parent - // process doesn't exist) - LOGGER.warning("The tasklist command: '" + command + "' returns " + process.exitValue()); - return true; - } - return !finished || process.exitValue() == 0; - } catch (IOException | InterruptedException e) { - LOGGER.log(Level.WARNING, e.getMessage(), e); - return true; - } finally { - if (process != null) { - if (!finished) { - process.destroyForcibly(); - } - // Terminating or destroying the Process doesn't close the process handle on - // Windows. - // It is only closed when the Process object is garbage collected (in its - // finalize() method). - // On Windows, when the Java LS is idle, we need to explicitly request a GC, - // to prevent an accumulation of zombie processes, as finalize() will be called. - if (isWindows) { - // Java >= 9 doesn't close the handle when the process is garbage collected - // We need to close the opened streams - if (!isJava1x) { - Closeables.closeQuietly(process.getInputStream()); - Closeables.closeQuietly(process.getErrorStream()); - try { - Closeables.close(process.getOutputStream(), false); - } catch (IOException e) { - } - } - System.gc(); - } - } - } - + Optional optionalHandle = ProcessHandle.of(pid); + return optionalHandle.isPresent() && optionalHandle.get().isAlive(); } @Override