diff --git a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/LanguageServerProcessReaper.java b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/LanguageServerProcessReaper.java
index e89310a73..2914db8d3 100644
--- a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/LanguageServerProcessReaper.java
+++ b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/LanguageServerProcessReaper.java
@@ -11,8 +11,9 @@
package org.springframework.tooling.ls.eclipse.commons;
import java.lang.reflect.Field;
+import java.util.HashMap;
import java.util.Iterator;
-import java.util.LinkedList;
+import java.util.Map;
import org.eclipse.core.runtime.Platform;
import org.eclipse.lsp4e.server.ProcessStreamConnectionProvider;
@@ -27,17 +28,17 @@ import org.eclipse.lsp4e.server.ProcessStreamConnectionProvider;
* something goes wrong inside lsp4e then the `destroyProcesses` method really should
* just be iterating an empty collection of processes. I.e. the typical debug output
* on shutdown should look something like this:
- *
+ *
*
- * LanguageServerProcessReaper: Destroying errant processes...
+ * LanguageServerProcessReaper: Destroying errant processes...
* LanguageServerProcessReaper: Number of alive processes = 0
* LanguageServerProcessReaper: Destroying errant processes... DONE
- *
- *
+ *
+ *
* @author Kris De Volder
*/
public class LanguageServerProcessReaper extends Thread {
-
+
private static final boolean DEBUG = (""+Platform.getLocation()).contains("kdvolder");
private static void debug(String string) {
@@ -59,15 +60,23 @@ public class LanguageServerProcessReaper extends Thread {
}
}
- LinkedList processes = new LinkedList<>();
+ Map processes = new HashMap<>();
{
Runtime.getRuntime().addShutdownHook(this);
}
-
- public synchronized void addProcess(Process process) {
+
+ public synchronized void addProcess(String id, Process process) {
debug("added process: "+process);
if (process!=null) {
- processes.add(process);
+ Process existingProcess = processes.get(id);
+ //workaround for this bug: https://bugs.eclipse.org/bugs/show_bug.cgi?id=549904
+ if (existingProcess!=null) {
+ if (existingProcess.isAlive()) {
+ debug("Destroying leaked process: "+process);
+ existingProcess.destroyForcibly();
+ }
+ }
+ processes.put(id, process);
}
garbageCollect();
}
@@ -79,7 +88,7 @@ public class LanguageServerProcessReaper extends Thread {
*/
protected void garbageCollect() {
Process process;
- Iterator iter = processes.iterator();
+ Iterator iter = processes.values().iterator();
while (iter.hasNext()) {
process = iter.next();
if (!process.isAlive()) {
@@ -102,7 +111,7 @@ public class LanguageServerProcessReaper extends Thread {
private synchronized void destroyProcesses() {
debug("Destroying errant processes... ");
garbageCollect();
- for (Process process : processes) {
+ for (Process process : processes.values()) {
try {
debug("Destroying process "+process);
process.destroyForcibly();
diff --git a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/STS4LanguageServerProcessStreamConnector.java b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/STS4LanguageServerProcessStreamConnector.java
index 93419a09b..e7d7a7d53 100644
--- a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/STS4LanguageServerProcessStreamConnector.java
+++ b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/STS4LanguageServerProcessStreamConnector.java
@@ -16,7 +16,9 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Path;
import java.util.List;
+import java.util.UUID;
+import org.apache.commons.lang3.exception.ExceptionUtils;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IProgressMonitor;
@@ -40,8 +42,10 @@ public abstract class STS4LanguageServerProcessStreamConnector extends ProcessSt
private static LanguageServerProcessReaper processReaper = new LanguageServerProcessReaper();
private Supplier consoles = null;
+ private final String connectorId;
public STS4LanguageServerProcessStreamConnector(ServerInfo server) {
+ this.connectorId = UUID.randomUUID().toString();
this.consoles = LanguageServerConsoles.getConsoleFactory(server);
}
@@ -49,7 +53,7 @@ public abstract class STS4LanguageServerProcessStreamConnector extends ProcessSt
public void start() throws IOException {
super.start();
Process process = LanguageServerProcessReaper.getProcess(this);
- processReaper.addProcess(process);
+ processReaper.addProcess(connectorId, process);
if (consoles!=null) {
Console console = consoles.get();
if (console!=null) {
@@ -146,12 +150,11 @@ public abstract class STS4LanguageServerProcessStreamConnector extends ProcessSt
protected IStatus run(IProgressMonitor arg0) {
try {
pipe(is, os);
- os.write("==== Process Terminated====\n".getBytes(Charsets.UTF_8));
} catch (IOException e) {
- e.printStackTrace();
}
finally {
try {
+ os.write("==== Process Terminated====\n".getBytes(Charsets.UTF_8));
os.close();
} catch (IOException e) {
}
diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/jdt/ls/JavaProjectsServiceWithFallback.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/jdt/ls/JavaProjectsServiceWithFallback.java
index 4bae271ba..a976b9d41 100644
--- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/jdt/ls/JavaProjectsServiceWithFallback.java
+++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/jdt/ls/JavaProjectsServiceWithFallback.java
@@ -10,6 +10,7 @@
*******************************************************************************/
package org.springframework.ide.vscode.boot.jdt.ls;
+import java.time.Duration;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@@ -79,6 +80,7 @@ public class JavaProjectsServiceWithFallback implements JavaProjectsService {
this.mainServiceInitialized = this.server
.onInitialized(main.initialize())
+ .timeout(Duration.ofSeconds(5))
.toFuture();
this.server.onShutdown(() -> {