diff --git a/plugins/org.python.pydev.debug/src/org/python/pydev/debug/processfactory/PyProcessFactory.java b/plugins/org.python.pydev.debug/src/org/python/pydev/debug/processfactory/PyProcessFactory.java
index 4610781..e08767f 100644
--- a/plugins/org.python.pydev.debug/src/org/python/pydev/debug/processfactory/PyProcessFactory.java
+++ b/plugins/org.python.pydev.debug/src/org/python/pydev/debug/processfactory/PyProcessFactory.java
@@ -9,8 +9,6 @@
import org.eclipse.debug.core.IProcessFactory;
import org.eclipse.debug.core.model.IProcess;
import org.eclipse.debug.core.model.RuntimeProcess;
-import org.jvnet.process_factory.AbstractProcess;
-import org.jvnet.process_factory.ProcessFactory;
import org.python.pydev.core.log.Log;
import org.python.pydev.debug.ui.RunPreferencesPage;
@@ -64,11 +62,10 @@
@Override
public void run() {
try {
- AbstractProcess p = ProcessFactory.createProcess(process);
+ UnixProcessKiller p = new UnixProcessKiller(process);
// I.e.: this is the real change in this wrapper: when killing a process, we'll kill the children
// processes too, not only the main process (i.e.: so that we don't have zombie processes alive for
// Django, etc).
- // Note: custom build from https://github.com/fabioz/winp (appveyor) to also support unix
p.killRecursively();
} catch (Exception e) {
Log.log(e);
diff --git a/plugins/org.python.pydev.debug/src/org/python/pydev/debug/processfactory/UnixProcessKiller.java b/plugins/org.python.pydev.debug/src/org/python/pydev/debug/processfactory/UnixProcessKiller.java
new file mode 100644
index 0000000..c8ec14f
--- /dev/null
+++ b/plugins/org.python.pydev.debug/src/org/python/pydev/debug/processfactory/UnixProcessKiller.java
@@ -0,0 +1,108 @@
+package org.python.pydev.debug.processfactory;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.lang.reflect.Field;
+import java.util.LinkedHashSet;
+import java.util.StringTokenizer;
+
+public class UnixProcessKiller {
+ private final int pid;
+
+ private static class Output {
+
+ public final String stdout;
+ public final String stderr;
+
+ public Output(String stdout, String stderr) {
+ this.stdout = stdout;
+ this.stderr = stderr;
+ }
+ }
+
+ public UnixProcessKiller(Process p)
+ throws Exception {
+ this.pid = getPid(p);
+ }
+
+ private static int getPid(Process process)
+ throws Exception {
+ try {
+ Field f = process.getClass().getDeclaredField("pid");
+ f.setAccessible(true);
+ return f.getInt(process);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void killRecursively()
+ throws IOException {
+ LinkedHashSet<Integer> listed = new LinkedHashSet<>();
+ killRecursively(pid, listed);
+ }
+
+ private static void killRecursively(int pid, LinkedHashSet<Integer> listed)
+ throws IOException {
+ listed.add(Integer.valueOf(pid));
+ Runtime.getRuntime().exec(new String[] {
+ "kill", "-stop", Integer.toString(pid)
+ }, null, null);
+ Process createProcess = Runtime.getRuntime().exec(new String[] {
+ "pgrep", "-P", Integer.toString(pid)
+ }, null, null);
+ Output outputPGrep = getProcessOutput(createProcess);
+ if (outputPGrep.stderr != null && outputPGrep.stderr.length() > 0) {
+ throw new RuntimeException(outputPGrep.stderr);
+ }
+ Runtime.getRuntime().exec(new String[] {
+ "kill", "-KILL", Integer.toString(pid)
+ }, null, null);
+ String ids = outputPGrep.stdout;
+ StringTokenizer strTok = new StringTokenizer(ids);
+ do {
+ if (!strTok.hasMoreTokens()) {
+ break;
+ }
+ String nextToken = strTok.nextToken();
+ int found = Integer.parseInt(nextToken);
+ if (!listed.contains(Integer.valueOf(found))) {
+ killRecursively(found, listed);
+ }
+ } while (true);
+ }
+
+ private static Output getProcessOutput(Process process)
+ throws IOException {
+ try {
+ process.getOutputStream().close();
+ } catch (IOException e2) {
+ }
+ InputStreamReader inputStream = new InputStreamReader(new BufferedInputStream(process.getInputStream()));
+ InputStreamReader errorStream = new InputStreamReader(new BufferedInputStream(process.getErrorStream()));
+ try {
+ process.waitFor();
+ } catch (InterruptedException e1) {
+ }
+ try {
+ Object sync = new Object();
+ synchronized (sync) {
+ sync.wait(10L);
+ }
+ } catch (Exception e) {
+ }
+ return new Output(readInputStream(inputStream), readInputStream(errorStream));
+ }
+
+ private static String readInputStream(InputStreamReader in)
+ throws IOException {
+ StringBuffer contents = new StringBuffer();
+ char buf[] = new char[80];
+ int c;
+ while ((c = in.read(buf)) != -1) {
+ contents.append(buf, 0, c);
+ }
+ return contents.toString();
+ }
+}
diff --git a/plugins/org.python.pydev.debug/build.properties b/plugins/org.python.pydev.debug/build.properties
index 0704b04..bf249fa 100644
--- a/plugins/org.python.pydev.debug/build.properties
+++ b/plugins/org.python.pydev.debug/build.properties
@@ -3,8 +3,7 @@
schema/,\
icons/,\
pydev-debug.jar,\
- LICENSE.txt,\
- libs/winp-1.26.0.7.jar
+ LICENSE.txt
jars.compile.order = pydev-debug.jar
source.pydev-debug.jar = src/,\
src_console/
diff --git a/plugins/org.python.pydev.debug/META-INF/MANIFEST.MF b/plugins/org.python.pydev.debug/META-INF/MANIFEST.MF
index e4ea072..12fd1ce 100644
--- a/plugins/org.python.pydev.debug/META-INF/MANIFEST.MF
+++ b/plugins/org.python.pydev.debug/META-INF/MANIFEST.MF
@@ -3,8 +3,7 @@ Bundle-ManifestVersion: 2
Bundle-Name: Pydev debug
Bundle-SymbolicName: org.python.pydev.debug; singleton:=true
Bundle-Version: 7.6.0.qualifier
-Bundle-ClassPath: pydev-debug.jar,
- libs/winp-1.26.0.7.jar
+Bundle-ClassPath: pydev-debug.jar
Bundle-Activator: org.python.pydev.debug.core.PydevDebugPlugin
Bundle-Vendor: Brainwy Software Ltda
Eclipse-BundleShape: dir