moved process reaper to commons and re-used it for boot-java-ls

This commit is contained in:
Martin Lippert
2017-11-03 20:20:27 +01:00
parent 546a81c3ce
commit af887117e7
5 changed files with 40 additions and 21 deletions

View File

@@ -7,7 +7,8 @@ Bundle-Version: 0.0.10.qualifier
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Require-Bundle: org.eclipse.jdt.launching;bundle-version="3.8.0",
org.eclipse.core.runtime;bundle-version="3.12.0",
org.eclipse.lsp4e;bundle-version="0.2.0"
org.eclipse.lsp4e;bundle-version="0.2.0",
org.springframework.tooling.ls.eclipse.commons;bundle-version="4.0.0"
Import-Package: org.eclipse.jface.preference,
org.eclipse.lsp4j;version="0.2.0.v20170518-0647",
org.eclipse.lsp4j.jsonrpc.messages;version="0.1.0.v20170117-0759",

View File

@@ -13,7 +13,6 @@ package org.springframework.tooling.cloudfoundry.manifest.ls;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
@@ -32,6 +31,7 @@ import org.eclipse.lsp4j.jsonrpc.messages.Message;
import org.eclipse.lsp4j.jsonrpc.messages.ResponseMessage;
import org.eclipse.lsp4j.services.LanguageServer;
import org.osgi.framework.Bundle;
import org.springframework.tooling.ls.eclipse.commons.LanguageServerProcessReaper;
/**
* @author Martin Lippert
@@ -93,7 +93,7 @@ public class CloudFoundryManifestLanguageServer extends ProcessStreamConnectionP
public void stop() {
removeLanguageServer(this);
super.stop();
processReaper.removeProcess(this.getProcess());
processReaper.removeProcess(LanguageServerProcessReaper.getProcess(this));
}
@Override
@@ -120,22 +120,9 @@ public class CloudFoundryManifestLanguageServer extends ProcessStreamConnectionP
@Override
public void start() throws IOException {
super.start();
processReaper.addProcess(getProcess());
processReaper.addProcess(LanguageServerProcessReaper.getProcess(this));
}
private Process getProcess() {
try {
//The super class is doesn't provide a way to get at the process without using reflection...
// This method can be removed if / when the super-class provides a getProcess method we can call.
Field processField = ProcessStreamConnectionProvider.class.getDeclaredField("process");
processField.setAccessible(true);
Process process = (Process) processField.get(this);
return process;
} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
return null;
}
}
protected String getLanguageServerJARLocation() {
String languageServer = "manifest-yaml-language-server-" + Constants.LANGUAGE_SERVER_VERSION;

View File

@@ -1,100 +0,0 @@
/*******************************************************************************
* Copyright (c) 2017 Spring IDE Developers
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Spring IDE Developers - initial API and implementation
*******************************************************************************/
package org.springframework.tooling.cloudfoundry.manifest.ls;
import java.util.Iterator;
import java.util.LinkedList;
import org.eclipse.core.runtime.Platform;
/**
* A 'last resort cleanup' utility for LSP server processes. This class, when instantiated
* registers a JVM shutdown hook. When the hook is executed it kills of all tracked processes
* with the most aggressive process termination method available through the JRE.
* <p>
* This is meant only as a kind of 'fail-safe' as it is expected that lps4e does proper
* house-keeping and cleans up these processes automatically and cleanly. So... unless
* 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:
*
* <pre>
* LanguageServerProcessReaper: Destroying errant processes...
* LanguageServerProcessReaper: Number of alive processes = 0
* LanguageServerProcessReaper: Destroying errant processes... DONE
* </pre>
*
* @author Kris De Volder
*/
public class LanguageServerProcessReaper extends Thread {
private static final boolean DEBUG = (""+Platform.getLocation()).contains("kdvolder");
private static void debug(String string) {
if (DEBUG) {
System.out.println("LanguageServerProcessReaper: "+string);
}
}
LinkedList<Process> processes = new LinkedList<>();
{
Runtime.getRuntime().addShutdownHook(this);
}
public synchronized void addProcess(Process process) {
debug("added process: "+process);
if (process!=null) {
processes.add(process);
}
garbageCollect();
}
/**
* If processes are managed reasonably by lsp4e then we don't expect the list of
* actually 'alive' processes to keep on growing. This checks for and removes
* processes that are already dead.
*/
protected void garbageCollect() {
Process process;
Iterator<Process> iter = processes.iterator();
while (iter.hasNext()) {
process = iter.next();
if (!process.isAlive()) {
iter.remove();
}
}
debug("Number of alive processes = "+processes.size());
}
public synchronized void removeProcess(Process process) {
debug("removeProcess "+process);
garbageCollect();
}
@Override
public void run() {
destroyProcesses();
}
private synchronized void destroyProcesses() {
debug("Destroying errant processes... ");
garbageCollect();
for (Process process : processes) {
try {
debug("Destroying process "+process);
process.destroyForcibly();
} catch (Throwable e) {
}
}
debug("Destroying errant processes... DONE");
}
}