Properly terminate child processes on windows

This applies to both SubCreator and SubServers. Only works on Java 9+ because Java 8 lacks a way to get the PIDs.
This commit is contained in:
ME1312 2019-01-04 18:32:01 -05:00
parent 1845e9d8f9
commit 9cb499c4ec
No known key found for this signature in database
GPG Key ID: FEFFE2F698E88FA8
6 changed files with 43 additions and 10 deletions

View File

@ -17,13 +17,13 @@ public class Executable {
*/
public static String[] parse(String gitbash, String exec) {
String[] cmd;
if (System.getProperty("os.name").toLowerCase().indexOf("win") >= 0) {
if (System.getProperty("os.name").toLowerCase().startsWith("windows")) {
if (gitbash != null && (exec.startsWith("bash ") || exec.startsWith("sh ")))
exec = "\"" + gitbash + ((gitbash.endsWith(File.separator))?"":File.separator) + "bin" + File.separatorChar + "sh.exe\" -lic \"" +
exec = "\"" + gitbash + ((gitbash.endsWith(File.separator))?"":File.separator) + "bin" + File.separatorChar + "sh.exe\" -lc \"" +
exec.replace("\\", "/\\").replace("\"", "\\\"").replace("^", "^^").replace("%", "^%").replace("&", "^&").replace("<", "^<").replace(">", "^>").replace("|", "^|") + "\"";
cmd = new String[]{"cmd.exe", "/q", "/c", '"'+exec+'"'};
} else {
cmd = new String[]{"sh", "-lic", exec};
cmd = new String[]{"sh", "-lc", exec};
}
return cmd;
}

View File

@ -128,7 +128,7 @@ public class InternalSubCreator extends SubCreator {
String command = "bash \"" + template.getBuildOptions().getRawString("Shell-Location") + '\"';
for (String arg : args) command += ' ' + arg;
if (System.getProperty("os.name").toLowerCase().indexOf("win") < 0 && template.getBuildOptions().contains("Permission")) {
if (!System.getProperty("os.name").toLowerCase().startsWith("windows") && template.getBuildOptions().contains("Permission")) {
try {
Process process = Runtime.getRuntime().exec("chmod " + template.getBuildOptions().getRawString("Permission") + ' ' + template.getBuildOptions().getRawString("Shell-Location"), null, dir);
Thread.sleep(500);
@ -347,9 +347,20 @@ public class InternalSubCreator extends SubCreator {
@Override
public void terminate(String name) {
if (this.thread.keySet().contains(name.toLowerCase())) {
boolean success = false;
if (this.thread.get(name.toLowerCase()).process != null && this.thread.get(name.toLowerCase()).process.isAlive() && System.getProperty("os.name").toLowerCase().startsWith("windows")) try {
Process terminator = Runtime.getRuntime().exec(new String[]{"taskkill", "/T", "/F", "/PID", Long.toString((long) Process.class.getDeclaredMethod("pid").invoke(this.thread.get(name.toLowerCase()).process))});
terminator.waitFor();
if (terminator.exitValue() != 0) throw new IllegalStateException("taskkill exited with code " + terminator.exitValue());
success = true;
} catch (Exception e) {}
if (this.thread.get(name.toLowerCase()).process != null && this.thread.get(name.toLowerCase()).process.isAlive()) {
this.thread.get(name.toLowerCase()).process.destroyForcibly();
} else if (this.thread.get(name.toLowerCase()).isAlive()) {
success = true;
}
if (!success && this.thread.get(name.toLowerCase()).isAlive()) {
this.thread.get(name.toLowerCase()).interrupt();
this.thread.remove(name.toLowerCase());
}

View File

@ -15,6 +15,7 @@ import net.md_5.bungee.BungeeServerInfo;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
@ -220,6 +221,11 @@ public class InternalSubServer extends SubServerContainer {
host.plugin.getPluginManager().callEvent(event);
if (!event.isCancelled()) {
allowrestart = false;
if (process != null && process.isAlive() && System.getProperty("os.name").toLowerCase().startsWith("windows")) try {
Process terminator = Runtime.getRuntime().exec(new String[]{"taskkill", "/T", "/F", "/PID", Long.toString((long) Process.class.getDeclaredMethod("pid").invoke(process))});
terminator.waitFor();
if (terminator.exitValue() != 0) throw new IllegalStateException("taskkill exited with code " + terminator.exitValue());
} catch (Exception e) {}
if (process != null && process.isAlive()) process.destroyForcibly();
return true;
} else return false;

View File

@ -17,13 +17,13 @@ public class Executable {
*/
public static String[] parse(String gitbash, String exec) {
String[] cmd;
if (System.getProperty("os.name").toLowerCase().indexOf("win") >= 0) {
if (System.getProperty("os.name").toLowerCase().startsWith("windows")) {
if (gitbash != null && (exec.startsWith("bash ") || exec.startsWith("sh ")))
exec = "\"" + gitbash + ((gitbash.endsWith(File.separator))?"":File.separator) + "bin" + File.separatorChar + "sh.exe\" -lic \"" +
exec = "\"" + gitbash + ((gitbash.endsWith(File.separator))?"":File.separator) + "bin" + File.separatorChar + "sh.exe\" -lc \"" +
exec.replace("\\", "/\\").replace("\"", "\\\"").replace("^", "^^").replace("%", "^%").replace("&", "^&").replace("<", "^<").replace(">", "^>").replace("|", "^|") + "\"";
cmd = new String[]{"cmd.exe", "/q", "/c", '"'+exec+'"'};
} else {
cmd = new String[]{"sh", "-lic", exec};
cmd = new String[]{"sh", "-lc", exec};
}
return cmd;
}

View File

@ -278,7 +278,7 @@ public class SubCreator {
String command = "bash \"" + template.getBuildOptions().getRawString("Shell-Location") + '\"';
for (String arg : args) command += ' ' + arg;
if (System.getProperty("os.name").toLowerCase().indexOf("win") < 0 && template.getBuildOptions().contains("Permission")) {
if (!System.getProperty("os.name").toLowerCase().startsWith("windows") && template.getBuildOptions().contains("Permission")) {
try {
Process process = Runtime.getRuntime().exec("chmod " + template.getBuildOptions().getRawString("Permission") + ' ' + template.getBuildOptions().getRawString("Shell-Location"), null, dir);
Thread.sleep(500);
@ -380,9 +380,20 @@ public class SubCreator {
public void terminate(String name) {
if (this.thread.keySet().contains(name.toLowerCase())) {
boolean success = false;
if (this.thread.get(name.toLowerCase()).process != null && this.thread.get(name.toLowerCase()).process.isAlive() && System.getProperty("os.name").toLowerCase().startsWith("windows")) try {
Process terminator = Runtime.getRuntime().exec(new String[]{"taskkill", "/T", "/F", "/PID", Long.toString((long) Process.class.getDeclaredMethod("pid").invoke(this.thread.get(name.toLowerCase()).process))});
terminator.waitFor();
if (terminator.exitValue() != 0) throw new IllegalStateException("taskkill exited with code " + terminator.exitValue());
success = true;
} catch (Exception e) {}
if (this.thread.get(name.toLowerCase()).process != null && this.thread.get(name.toLowerCase()).process.isAlive()) {
this.thread.get(name.toLowerCase()).process.destroyForcibly();
} else if (this.thread.get(name.toLowerCase()).isAlive()) {
success = true;
}
if (!success && this.thread.get(name.toLowerCase()).isAlive()) {
this.thread.get(name.toLowerCase()).interrupt();
this.thread.remove(name.toLowerCase());
}

View File

@ -167,6 +167,11 @@ public class SubServer {
*/
public void terminate() {
allowrestart = false;
if (process != null && process.isAlive() && System.getProperty("os.name").toLowerCase().startsWith("windows")) try {
Process terminator = Runtime.getRuntime().exec(new String[]{"taskkill", "/T", "/F", "/PID", Long.toString((long) Process.class.getDeclaredMethod("pid").invoke(process))});
terminator.waitFor();
if (terminator.exitValue() != 0) throw new IllegalStateException("taskkill exited with code " + terminator.exitValue());
} catch (Exception e) {}
if (process != null && process.isAlive()) process.destroyForcibly();
}