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
@@ -8,8 +8,6 @@ import org.eclipse.debug.core.ILaunch;
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.DebugPrefsPage;
@@ -59,9 +57,9 @@ public class PyProcessFactory implements IProcessFactory {
public void destroy() {
if (DebugPrefsPage.getKillSubprocessesWhenTerminatingProcess()) {
try {
- AbstractProcess p = ProcessFactory.CreateProcess(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
+ 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).
p.killRecursively();
} catch (Exception 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/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: 4.5.5.qualifier
-Bundle-ClassPath: pydev-debug.jar,
- libs/winp-1.19.jar
+Bundle-ClassPath: pydev-debug.jar
Bundle-Activator: org.python.pydev.debug.core.PydevDebugPlugin
Bundle-Vendor: Aptana
Bundle-Localization: plugin
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
@@ -1,5 +1,4 @@
bin.includes = plugin.xml,\
- libs/winp-1.19.jar,\
META-INF/,\
schema/,\
icons/,\