Skip to content

Commit

Permalink
Add PID termination in Java 8
Browse files Browse the repository at this point in the history
Some trickery was applied, but its okay since Java 9 has proper API methods for this stuff anyway
  • Loading branch information
ME1312 committed Jan 9, 2019
1 parent 0d46c5b commit abaa2f3
Show file tree
Hide file tree
Showing 9 changed files with 138 additions and 40 deletions.
6 changes: 6 additions & 0 deletions SubServers.Bungee/pom.xml
Expand Up @@ -27,6 +27,12 @@
<version>1.9-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna-platform</artifactId>
<version>5.2.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.msgpack</groupId>
<artifactId>msgpack-core</artifactId>
Expand Down
@@ -1,6 +1,11 @@
package net.ME1312.SubServers.Bungee.Host;

import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.WinNT;

import java.io.File;
import java.lang.reflect.Field;

/**
* Executable String Handler Class
Expand All @@ -27,4 +32,58 @@ public static String[] parse(String gitbash, String exec) {
}
return cmd;
}

/**
* Get the PID of a currently running process
*
* @param process Process
* @return Process ID
*/
public static Long pid(Process process) {
if (process.isAlive()) {
try {
return (long) Process.class.getDeclaredMethod("pid").invoke(process);
} catch (Throwable ex) {
try {
if (process.getClass().getName().equals("java.lang.Win32Process") || process.getClass().getName().equals("java.lang.ProcessImpl")) {
Field f = process.getClass().getDeclaredField("handle");
f.setAccessible(true);
long handle = f.getLong(process);
f.setAccessible(false);

Kernel32 k32 = Kernel32.INSTANCE;
WinNT.HANDLE nt = new WinNT.HANDLE();
nt.setPointer(Pointer.createConstant(handle));
return (long) k32.GetProcessId(nt);
} else if (process.getClass().getName().equals("java.lang.UNIXProcess")) {
Field f = process.getClass().getDeclaredField("pid");
f.setAccessible(true);
Object response = f.get(process);
f.setAccessible(false);

if (response instanceof Number) return ((Number) response).longValue();
}
} catch (Throwable e) {}
}
}
return null;
}

/**
* Terminate a currently running process
*
* @param process Process
*/
public static void terminate(Process process) {
if (process.isAlive()) {
if (System.getProperty("os.name").toLowerCase().startsWith("windows")) {
Long pid = pid(process);
if (pid != null) try {
Process terminator = Runtime.getRuntime().exec(new String[]{"taskkill", "/T", "/F", "/PID", pid.toString()});
terminator.waitFor();
} catch (Throwable e) {}
}
if (process.isAlive()) process.destroyForcibly();
}
}
}
Expand Up @@ -358,20 +358,9 @@ public void terminate() {
@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();
success = true;
}

if (!success && this.thread.get(name.toLowerCase()).isAlive()) {
Executable.terminate(this.thread.get(name.toLowerCase()).process);
} else if (this.thread.get(name.toLowerCase()).isAlive()) {
this.thread.get(name.toLowerCase()).interrupt();
this.thread.remove(name.toLowerCase());
}
Expand Down
Expand Up @@ -221,12 +221,7 @@ public boolean terminate(UUID player) {
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();
if (process != null && process.isAlive()) Executable.terminate(process);
return true;
} else return false;
} else return false;
Expand Down
Expand Up @@ -766,7 +766,7 @@ public void run(YAMLSection json) {
return CommandResult.builder().successCount(0).build();
}
} else {
sender.sendMessage(ChatColor.convertColor(plugin.api.getLang("SubServers","Command.Generic.Usage").replace("$str$", "/sub stop <SubServer>")));
sender.sendMessage(ChatColor.convertColor(plugin.api.getLang("SubServers","Command.Generic.Usage").replace("$str$", "/sub restart <SubServer>")));
return CommandResult.builder().successCount(0).build();
}
} else {
Expand Down
8 changes: 7 additions & 1 deletion SubServers.Host/pom.xml
Expand Up @@ -20,7 +20,13 @@
<dependency>
<groupId>net.ME1312.Galaxi</groupId>
<artifactId>GalaxiEngine</artifactId>
<version>19w02d</version>
<version>19w02e</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna-platform</artifactId>
<version>5.2.0</version>
<scope>compile</scope>
</dependency>
<dependency>
Expand Down
@@ -1,6 +1,11 @@
package net.ME1312.SubServers.Host.Executable;

import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.WinNT;

import java.io.File;
import java.lang.reflect.Field;

/**
* Executable String Handler Class
Expand All @@ -27,4 +32,58 @@ public static String[] parse(String gitbash, String exec) {
}
return cmd;
}

/**
* Get the PID of a currently running process
*
* @param process Process
* @return Process ID
*/
public static Long pid(Process process) {
if (process.isAlive()) {
try {
return (long) Process.class.getDeclaredMethod("pid").invoke(process);
} catch (Throwable ex) {
try {
if (process.getClass().getName().equals("java.lang.Win32Process") || process.getClass().getName().equals("java.lang.ProcessImpl")) {
Field f = process.getClass().getDeclaredField("handle");
f.setAccessible(true);
long handle = f.getLong(process);
f.setAccessible(false);

Kernel32 k32 = Kernel32.INSTANCE;
WinNT.HANDLE nt = new WinNT.HANDLE();
nt.setPointer(Pointer.createConstant(handle));
return (long) k32.GetProcessId(nt);
} else if (process.getClass().getName().equals("java.lang.UNIXProcess")) {
Field f = process.getClass().getDeclaredField("pid");
f.setAccessible(true);
Object response = f.get(process);
f.setAccessible(false);

if (response instanceof Number) return ((Number) response).longValue();
}
} catch (Throwable e) {}
}
}
return null;
}

/**
* Terminate a currently running process
*
* @param process Process
*/
public static void terminate(Process process) {
if (process.isAlive()) {
if (System.getProperty("os.name").toLowerCase().startsWith("windows")) {
Long pid = pid(process);
if (pid != null) try {
Process terminator = Runtime.getRuntime().exec(new String[]{"taskkill", "/T", "/F", "/PID", pid.toString()});
terminator.waitFor();
} catch (Throwable e) {}
}
if (process.isAlive()) process.destroyForcibly();
}
}
}
Expand Up @@ -382,20 +382,9 @@ public void terminate() {

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();
success = true;
}

if (!success && this.thread.get(name.toLowerCase()).isAlive()) {
Executable.terminate(this.thread.get(name.toLowerCase()).process);
} else if (this.thread.get(name.toLowerCase()).isAlive()) {
this.thread.get(name.toLowerCase()).interrupt();
this.thread.remove(name.toLowerCase());
}
Expand Down
Expand Up @@ -168,12 +168,7 @@ public void stop() {
*/
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();
if (process != null && process.isAlive()) Executable.terminate(process);
}

/**
Expand Down

0 comments on commit abaa2f3

Please sign in to comment.