Blame SOURCES/fix-process-killing.patch

41b21e
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
41b21e
index 4610781..e08767f 100644
41b21e
--- a/plugins/org.python.pydev.debug/src/org/python/pydev/debug/processfactory/PyProcessFactory.java
41b21e
+++ b/plugins/org.python.pydev.debug/src/org/python/pydev/debug/processfactory/PyProcessFactory.java
41b21e
@@ -8,8 +8,6 @@ import org.eclipse.debug.core.ILaunch;
41b21e
 import org.eclipse.debug.core.IProcessFactory;
41b21e
 import org.eclipse.debug.core.model.IProcess;
41b21e
 import org.eclipse.debug.core.model.RuntimeProcess;
41b21e
-import org.jvnet.process_factory.AbstractProcess;
41b21e
-import org.jvnet.process_factory.ProcessFactory;
41b21e
 import org.python.pydev.core.log.Log;
41b21e
 import org.python.pydev.debug.ui.DebugPrefsPage;
41b21e
 
41b21e
@@ -59,9 +57,9 @@ public class PyProcessFactory implements IProcessFactory {
41b21e
         public void destroy() {
41b21e
             if (DebugPrefsPage.getKillSubprocessesWhenTerminatingProcess()) {
41b21e
                 try {
41b21e
-                    AbstractProcess p = ProcessFactory.CreateProcess(process);
41b21e
-                    //I.e.: this is the real change in this wrapper: when killing a process, we'll kill the children 
41b21e
-                    //processes too, not only the main process (i.e.: so that we don't have zombie processes alive for 
41b21e
+                    UnixProcessKiller p = new UnixProcessKiller(process);
41b21e
+                    //I.e.: this is the real change in this wrapper: when killing a process, we'll kill the children
41b21e
+                    //processes too, not only the main process (i.e.: so that we don't have zombie processes alive for
41b21e
                     //Django, etc).
41b21e
                     p.killRecursively();
41b21e
                 } catch (Exception e) {
41b21e
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
41b21e
new file mode 100644
41b21e
index 0000000..c8ec14f
41b21e
--- /dev/null
41b21e
+++ b/plugins/org.python.pydev.debug/src/org/python/pydev/debug/processfactory/UnixProcessKiller.java
41b21e
@@ -0,0 +1,108 @@
41b21e
+package org.python.pydev.debug.processfactory;
41b21e
+
41b21e
+import java.io.BufferedInputStream;
41b21e
+import java.io.IOException;
41b21e
+import java.io.InputStreamReader;
41b21e
+import java.lang.reflect.Field;
41b21e
+import java.util.LinkedHashSet;
41b21e
+import java.util.StringTokenizer;
41b21e
+
41b21e
+public class UnixProcessKiller {
41b21e
+    private final int pid;
41b21e
+
41b21e
+    private static class Output {
41b21e
+
41b21e
+        public final String stdout;
41b21e
+        public final String stderr;
41b21e
+
41b21e
+        public Output(String stdout, String stderr) {
41b21e
+            this.stdout = stdout;
41b21e
+            this.stderr = stderr;
41b21e
+        }
41b21e
+    }
41b21e
+
41b21e
+    public UnixProcessKiller(Process p)
41b21e
+            throws Exception {
41b21e
+        this.pid = getPid(p);
41b21e
+    }
41b21e
+
41b21e
+    private static int getPid(Process process)
41b21e
+            throws Exception {
41b21e
+        try {
41b21e
+            Field f = process.getClass().getDeclaredField("pid");
41b21e
+            f.setAccessible(true);
41b21e
+            return f.getInt(process);
41b21e
+        } catch (Exception e) {
41b21e
+            throw new RuntimeException(e);
41b21e
+        }
41b21e
+    }
41b21e
+
41b21e
+    public void killRecursively()
41b21e
+            throws IOException {
41b21e
+        LinkedHashSet<Integer> listed = new LinkedHashSet<>();
41b21e
+        killRecursively(pid, listed);
41b21e
+    }
41b21e
+
41b21e
+    private static void killRecursively(int pid, LinkedHashSet<Integer> listed)
41b21e
+            throws IOException {
41b21e
+        listed.add(Integer.valueOf(pid));
41b21e
+        Runtime.getRuntime().exec(new String[] {
41b21e
+                "kill", "-stop", Integer.toString(pid)
41b21e
+        }, null, null);
41b21e
+        Process createProcess = Runtime.getRuntime().exec(new String[] {
41b21e
+                "pgrep", "-P", Integer.toString(pid)
41b21e
+        }, null, null);
41b21e
+        Output outputPGrep = getProcessOutput(createProcess);
41b21e
+        if (outputPGrep.stderr != null && outputPGrep.stderr.length() > 0) {
41b21e
+            throw new RuntimeException(outputPGrep.stderr);
41b21e
+        }
41b21e
+        Runtime.getRuntime().exec(new String[] {
41b21e
+                "kill", "-KILL", Integer.toString(pid)
41b21e
+        }, null, null);
41b21e
+        String ids = outputPGrep.stdout;
41b21e
+        StringTokenizer strTok = new StringTokenizer(ids);
41b21e
+        do {
41b21e
+            if (!strTok.hasMoreTokens()) {
41b21e
+                break;
41b21e
+            }
41b21e
+            String nextToken = strTok.nextToken();
41b21e
+            int found = Integer.parseInt(nextToken);
41b21e
+            if (!listed.contains(Integer.valueOf(found))) {
41b21e
+                killRecursively(found, listed);
41b21e
+            }
41b21e
+        } while (true);
41b21e
+    }
41b21e
+
41b21e
+    private static Output getProcessOutput(Process process)
41b21e
+            throws IOException {
41b21e
+        try {
41b21e
+            process.getOutputStream().close();
41b21e
+        } catch (IOException e2) {
41b21e
+        }
41b21e
+        InputStreamReader inputStream = new InputStreamReader(new BufferedInputStream(process.getInputStream()));
41b21e
+        InputStreamReader errorStream = new InputStreamReader(new BufferedInputStream(process.getErrorStream()));
41b21e
+        try {
41b21e
+            process.waitFor();
41b21e
+        } catch (InterruptedException e1) {
41b21e
+        }
41b21e
+        try {
41b21e
+            Object sync = new Object();
41b21e
+            synchronized (sync) {
41b21e
+                sync.wait(10L);
41b21e
+            }
41b21e
+        } catch (Exception e) {
41b21e
+        }
41b21e
+        return new Output(readInputStream(inputStream), readInputStream(errorStream));
41b21e
+    }
41b21e
+
41b21e
+    private static String readInputStream(InputStreamReader in)
41b21e
+            throws IOException {
41b21e
+        StringBuffer contents = new StringBuffer();
41b21e
+        char buf[] = new char[80];
41b21e
+        int c;
41b21e
+        while ((c = in.read(buf)) != -1) {
41b21e
+            contents.append(buf, 0, c);
41b21e
+        }
41b21e
+        return contents.toString();
41b21e
+    }
41b21e
+}
41b21e
diff --git a/plugins/org.python.pydev.debug/META-INF/MANIFEST.MF b/plugins/org.python.pydev.debug/META-INF/MANIFEST.MF
dc00b4
index e4ea072..12fd1ce 100644
41b21e
--- a/plugins/org.python.pydev.debug/META-INF/MANIFEST.MF
41b21e
+++ b/plugins/org.python.pydev.debug/META-INF/MANIFEST.MF
41b21e
@@ -3,8 +3,7 @@ Bundle-ManifestVersion: 2
41b21e
 Bundle-Name: Pydev debug
41b21e
 Bundle-SymbolicName: org.python.pydev.debug; singleton:=true
dc00b4
 Bundle-Version: 4.5.5.qualifier
41b21e
-Bundle-ClassPath: pydev-debug.jar,
41b21e
- libs/winp-1.19.jar
41b21e
+Bundle-ClassPath: pydev-debug.jar
41b21e
 Bundle-Activator: org.python.pydev.debug.core.PydevDebugPlugin
41b21e
 Bundle-Vendor: Aptana
41b21e
 Bundle-Localization: plugin
41b21e
diff --git a/plugins/org.python.pydev.debug/build.properties b/plugins/org.python.pydev.debug/build.properties
41b21e
index 0704b04..bf249fa 100644
41b21e
--- a/plugins/org.python.pydev.debug/build.properties
41b21e
+++ b/plugins/org.python.pydev.debug/build.properties
41b21e
@@ -1,5 +1,4 @@
41b21e
 bin.includes = plugin.xml,\
41b21e
-               libs/winp-1.19.jar,\
41b21e
                META-INF/,\
41b21e
                schema/,\
41b21e
                icons/,\