1212 *******************************************************************************/
1313package org .eclipse .lemminx .commons ;
1414
15- import static org .eclipse .lemminx .utils .platform .Platform .isWindows ;
16-
17- import java .io .IOException ;
15+ import java .util .Optional ;
1816import java .util .concurrent .Executors ;
1917import java .util .concurrent .ScheduledExecutorService ;
2018import java .util .concurrent .ScheduledFuture ;
2119import java .util .concurrent .TimeUnit ;
2220import java .util .function .Function ;
23- import java .util .logging .Level ;
2421import java .util .logging .Logger ;
2522
26- import com .google .common .io .Closeables ;
27-
2823import org .eclipse .lsp4j .jsonrpc .MessageConsumer ;
2924import org .eclipse .lsp4j .services .LanguageServer ;
3025
3631public final class ParentProcessWatcher implements Runnable , Function <MessageConsumer , MessageConsumer > {
3732
3833 private static final Logger LOGGER = Logger .getLogger (ParentProcessWatcher .class .getName ());
39- private static final boolean isJava1x = System .getProperty ("java.version" ).startsWith ("1." );
4034
4135 /**
4236 * Exit code returned when XML Language Server is forced to exit.
@@ -46,9 +40,9 @@ public final class ParentProcessWatcher implements Runnable, Function<MessageCon
4640 private static final long INACTIVITY_DELAY_SECS = 30 * 1000 ;
4741 private static final int POLL_DELAY_SECS = 10 ;
4842 private volatile long lastActivityTime ;
49- private final ProcessLanguageServer server ;
5043 private ScheduledFuture <?> task ;
5144 private ScheduledExecutorService service ;
45+ private ProcessLanguageServer server ;
5246
5347 public interface ProcessLanguageServer extends LanguageServer {
5448
@@ -84,55 +78,8 @@ private boolean parentProcessStillRunning() {
8478 if (pid == 0 || lastActivityTime > (System .currentTimeMillis () - INACTIVITY_DELAY_SECS )) {
8579 return true ;
8680 }
87- String command ;
88- if (isWindows ) {
89- command = "cmd /c \" tasklist /FI \" PID eq " + pid + "\" | findstr " + pid + "\" " ;
90- } else {
91- command = "kill -0 " + pid ;
92- }
93- Process process = null ;
94- boolean finished = false ;
95- try {
96- process = Runtime .getRuntime ().exec (command );
97- finished = process .waitFor (POLL_DELAY_SECS , TimeUnit .SECONDS );
98- if (!finished ) {
99- process .destroy ();
100- finished = process .waitFor (POLL_DELAY_SECS , TimeUnit .SECONDS ); // wait for the process to stop
101- }
102- if (isWindows && finished && process .exitValue () > 1 ) {
103- // the tasklist command should return 0 (parent process exists) or 1 (parent process doesn't exist)
104- LOGGER .warning ("The tasklist command: '" + command + "' returns " + process .exitValue ());
105- return true ;
106- }
107- return !finished || process .exitValue () == 0 ;
108- } catch (IOException | InterruptedException e ) {
109- LOGGER .log (Level .WARNING , e .getMessage (), e );
110- return true ;
111- } finally {
112- if (process != null ) {
113- if (!finished ) {
114- process .destroyForcibly ();
115- }
116- // Terminating or destroying the Process doesn't close the process handle on Windows.
117- // It is only closed when the Process object is garbage collected (in its finalize() method).
118- // On Windows, when the Java LS is idle, we need to explicitly request a GC,
119- // to prevent an accumulation of zombie processes, as finalize() will be called.
120- if (isWindows ) {
121- // Java >= 9 doesn't close the handle when the process is garbage collected
122- // We need to close the opened streams
123- if (!isJava1x ) {
124- Closeables .closeQuietly (process .getInputStream ());
125- Closeables .closeQuietly (process .getErrorStream ());
126- try {
127- Closeables .close (process .getOutputStream (), false );
128- } catch (IOException e ) {
129- }
130- }
131- System .gc ();
132- }
133- }
134- }
135-
81+ Optional <ProcessHandle > optionalHandle = ProcessHandle .of (pid );
82+ return !optionalHandle .isEmpty () && optionalHandle .get ().isAlive ();
13683 }
13784
13885 @ Override
0 commit comments