You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@gump.apache.org by le...@apache.org on 2005/07/13 11:59:03 UTC

svn commit: r216132 - /gump/branches/Gump3/pygump/setpgrpbug/

Author: leosimons
Date: Wed Jul 13 02:59:02 2005
New Revision: 216132

URL: http://svn.apache.org/viewcvs?rev=216132&view=rev
Log:
Add my not-useful testcase for the setpgrp bug so Stefan can take a look at it.

Added:
    gump/branches/Gump3/pygump/setpgrpbug/
    gump/branches/Gump3/pygump/setpgrpbug/ExecuteStreamHandler.class   (with props)
    gump/branches/Gump3/pygump/setpgrpbug/ExecuteStreamHandler.java
    gump/branches/Gump3/pygump/setpgrpbug/Java13CommandLauncher.class   (with props)
    gump/branches/Gump3/pygump/setpgrpbug/Java13CommandLauncher.java
    gump/branches/Gump3/pygump/setpgrpbug/Main.class   (with props)
    gump/branches/Gump3/pygump/setpgrpbug/Main.java
    gump/branches/Gump3/pygump/setpgrpbug/Main2.class   (with props)
    gump/branches/Gump3/pygump/setpgrpbug/Main2.java
    gump/branches/Gump3/pygump/setpgrpbug/ProcessDestroyer$ProcessDestroyerImpl.class   (with props)
    gump/branches/Gump3/pygump/setpgrpbug/ProcessDestroyer.class   (with props)
    gump/branches/Gump3/pygump/setpgrpbug/ProcessDestroyer.java
    gump/branches/Gump3/pygump/setpgrpbug/PumpStreamHandler.class   (with props)
    gump/branches/Gump3/pygump/setpgrpbug/PumpStreamHandler.java
    gump/branches/Gump3/pygump/setpgrpbug/StreamPumper.class   (with props)
    gump/branches/Gump3/pygump/setpgrpbug/StreamPumper.java
    gump/branches/Gump3/pygump/setpgrpbug/ant-nodeps.jar   (with props)
    gump/branches/Gump3/pygump/setpgrpbug/jaxp-api.jar   (with props)
    gump/branches/Gump3/pygump/setpgrpbug/resolver.jar   (with props)
    gump/branches/Gump3/pygump/setpgrpbug/run   (with props)
    gump/branches/Gump3/pygump/setpgrpbug/run.py
    gump/branches/Gump3/pygump/setpgrpbug/sax.jar   (with props)
    gump/branches/Gump3/pygump/setpgrpbug/which.jar   (with props)
    gump/branches/Gump3/pygump/setpgrpbug/xercesImpl.jar   (with props)
    gump/branches/Gump3/pygump/setpgrpbug/xml-apis.jar   (with props)

Added: gump/branches/Gump3/pygump/setpgrpbug/ExecuteStreamHandler.class
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/pygump/setpgrpbug/ExecuteStreamHandler.class?rev=216132&view=auto
==============================================================================
Binary file - no diff available.

Propchange: gump/branches/Gump3/pygump/setpgrpbug/ExecuteStreamHandler.class
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: gump/branches/Gump3/pygump/setpgrpbug/ExecuteStreamHandler.java
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/pygump/setpgrpbug/ExecuteStreamHandler.java?rev=216132&view=auto
==============================================================================
--- gump/branches/Gump3/pygump/setpgrpbug/ExecuteStreamHandler.java (added)
+++ gump/branches/Gump3/pygump/setpgrpbug/ExecuteStreamHandler.java Wed Jul 13 02:59:02 2005
@@ -0,0 +1,67 @@
+/*
+ * Copyright  2000,2002,2004-2005 The Apache Software Foundation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+// MODIFIED FROM ANT CVS HEAD:
+//    http://cvs.apache.org/viewcvs.cgi/ant/src/main/org/apache/tools/ant/taskdefs/
+/**
+ * Used by <code>Execute</code> to handle input and output stream of
+ * subprocesses.
+ *
+ * @since Ant 1.2
+ */
+public interface ExecuteStreamHandler {
+
+    /**
+     * Install a handler for the input stream of the subprocess.
+     *
+     * @param os output stream to write to the standard input stream of the
+     *           subprocess
+     * @throws IOException on error
+     */
+    void setProcessInputStream(OutputStream os) throws IOException;
+
+    /**
+     * Install a handler for the error stream of the subprocess.
+     *
+     * @param is input stream to read from the error stream from the subprocess
+     * @throws IOException on error
+     */
+    void setProcessErrorStream(InputStream is) throws IOException;
+
+    /**
+     * Install a handler for the output stream of the subprocess.
+     *
+     * @param is input stream to read from the error stream from the subprocess
+     * @throws IOException on error
+     */
+    void setProcessOutputStream(InputStream is) throws IOException;
+
+    /**
+     * Start handling of the streams.
+     * @throws IOException on error
+     */
+    void start() throws IOException;
+
+    /**
+     * Stop handling of the streams - will not be restarted.
+     */
+    void stop();
+}

Added: gump/branches/Gump3/pygump/setpgrpbug/Java13CommandLauncher.class
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/pygump/setpgrpbug/Java13CommandLauncher.class?rev=216132&view=auto
==============================================================================
Binary file - no diff available.

Propchange: gump/branches/Gump3/pygump/setpgrpbug/Java13CommandLauncher.class
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: gump/branches/Gump3/pygump/setpgrpbug/Java13CommandLauncher.java
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/pygump/setpgrpbug/Java13CommandLauncher.java?rev=216132&view=auto
==============================================================================
--- gump/branches/Gump3/pygump/setpgrpbug/Java13CommandLauncher.java (added)
+++ gump/branches/Gump3/pygump/setpgrpbug/Java13CommandLauncher.java Wed Jul 13 02:59:02 2005
@@ -0,0 +1,39 @@
+/*
+ * Copyright  2000,2002,2004-2005 The Apache Software Foundation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+import java.lang.reflect.Method;
+import java.io.File;
+
+// MODIFIED FROM ANT CVS HEAD:
+//    http://cvs.apache.org/viewcvs.cgi/ant/src/main/org/apache/tools/ant/taskdefs/    
+    public class Java13CommandLauncher {
+        private Method myExecWithCWD;
+
+        public Java13CommandLauncher() throws Exception {
+            System.out.println("  Main.java line #21");
+            // Locate method Runtime.exec(String[] cmdarray,
+            //                            String[] envp, File dir)
+            myExecWithCWD = Runtime.class.getMethod("exec",
+                    new Class[] {String[].class, String[].class, File.class});
+        }
+
+        public Process exec(String[] cmd, String[] env,
+                            File workingDir) throws Exception {
+            System.out.println("  Main.java line #41");
+            return (Process) myExecWithCWD.invoke(Runtime.getRuntime(),
+                   new Object[] {cmd, env, workingDir});
+        }
+    }

Added: gump/branches/Gump3/pygump/setpgrpbug/Main.class
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/pygump/setpgrpbug/Main.class?rev=216132&view=auto
==============================================================================
Binary file - no diff available.

Propchange: gump/branches/Gump3/pygump/setpgrpbug/Main.class
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: gump/branches/Gump3/pygump/setpgrpbug/Main.java
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/pygump/setpgrpbug/Main.java?rev=216132&view=auto
==============================================================================
--- gump/branches/Gump3/pygump/setpgrpbug/Main.java (added)
+++ gump/branches/Gump3/pygump/setpgrpbug/Main.java Wed Jul 13 02:59:02 2005
@@ -0,0 +1,109 @@
+/*
+ * Copyright  2000,2002,2004-2005 The Apache Software Foundation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+// MODIFIED FROM ANT CVS HEAD:
+//    http://cvs.apache.org/viewcvs.cgi/ant/src/main/org/apache/tools/ant/taskdefs/
+public class Main {
+    private static ProcessDestroyer processDestroyer = new ProcessDestroyer();
+    private int exitValue;
+    
+    public static void main(String[] args) throws Exception {
+      Main main = new Main();
+      int result = main.start(args);
+    }
+    public int start(String[] args) throws Exception {
+        System.out.println("  Main.java line #33");
+        System.err.println("  Main.java line #34 (to stderr)");
+        
+        String javahome = args[0];
+        System.out.println("  Java home is " + javahome);
+    
+        Java13CommandLauncher launcher = new Java13CommandLauncher();
+        ExecuteStreamHandler streamHandler = new PumpStreamHandler();
+        
+        String[] command = new String[] {javahome + "/bin/java", "Main2"};
+        String[] env = new String[] {"JAVA_HOME=" + javahome};
+        File dir = new File(".");
+
+        Process process = launcher.exec(command, env, dir);
+        try {
+            streamHandler.setProcessInputStream(process.getOutputStream());
+            streamHandler.setProcessOutputStream(process.getInputStream());
+            streamHandler.setProcessErrorStream(process.getErrorStream());
+        } catch (IOException e) {
+            process.destroy();
+            throw e;
+        }
+        streamHandler.start();
+
+        try {
+            processDestroyer.add(process);
+
+            waitFor(process);
+
+            streamHandler.stop();
+            closeStreams(process);
+
+            return exitValue;
+        } catch (ThreadDeath t) {
+            // #31928: forcibly kill it before continuing.
+            process.destroy();
+            throw t;
+        } finally {
+            // remove the process to the list of those to destroy if
+            // the VM exits
+            //
+            processDestroyer.remove(process);
+        }
+    }
+  
+    protected void waitFor(Process process) {
+        try {
+            process.waitFor();
+            exitValue = process.exitValue();
+        } catch (InterruptedException e) {
+            process.destroy();
+        }
+    }
+    public static void closeStreams(Process process) {
+        close(process.getInputStream());
+        close(process.getOutputStream());
+        close(process.getErrorStream());
+    }
+    public static void close(InputStream device) {
+        if (device != null) {
+            try {
+                device.close();
+            } catch (IOException ioex) {
+                //ignore
+            }
+        }
+    }
+    public static void close(OutputStream device) {
+        if (device != null) {
+            try {
+                device.close();
+            } catch (IOException ioex) {
+                //ignore
+            }
+        }
+    }
+}

Added: gump/branches/Gump3/pygump/setpgrpbug/Main2.class
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/pygump/setpgrpbug/Main2.class?rev=216132&view=auto
==============================================================================
Binary file - no diff available.

Propchange: gump/branches/Gump3/pygump/setpgrpbug/Main2.class
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: gump/branches/Gump3/pygump/setpgrpbug/Main2.java
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/pygump/setpgrpbug/Main2.java?rev=216132&view=auto
==============================================================================
--- gump/branches/Gump3/pygump/setpgrpbug/Main2.java (added)
+++ gump/branches/Gump3/pygump/setpgrpbug/Main2.java Wed Jul 13 02:59:02 2005
@@ -0,0 +1,37 @@
+import java.io.FileInputStream;
+import java.io.BufferedInputStream;
+
+public class Main2
+{
+  public static void main(String[] args) throws Exception {
+    System.out.println("  Main2 line 4");
+    System.err.println("  Main2 line 5 (to stderr)");
+
+    System.out.println("  Main2 changing input...");
+    FileInputStream input = new FileInputStream("Main2.java");
+    System.setIn(input);
+    System.gc();
+    
+    processInput();
+    System.err.println("  Main2 is done processing...");
+    System.gc();
+    System.err.println("  Going to sleep for a bit...");
+    Thread.sleep(2000);
+    System.err.println("  Woke up!");
+      }
+  
+  public static void processInput() throws Exception
+  {
+    BufferedInputStream input = new BufferedInputStream(System.in);
+    System.err.println("Echoing Main2.java");
+    while(true)
+    {
+      int b = input.read();
+      if( b == -1 )
+      {
+        return;
+      }
+      System.out.write(b);
+    }
+  }
+}

Added: gump/branches/Gump3/pygump/setpgrpbug/ProcessDestroyer$ProcessDestroyerImpl.class
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/pygump/setpgrpbug/ProcessDestroyer%24ProcessDestroyerImpl.class?rev=216132&view=auto
==============================================================================
Binary file - no diff available.

Propchange: gump/branches/Gump3/pygump/setpgrpbug/ProcessDestroyer$ProcessDestroyerImpl.class
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: gump/branches/Gump3/pygump/setpgrpbug/ProcessDestroyer.class
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/pygump/setpgrpbug/ProcessDestroyer.class?rev=216132&view=auto
==============================================================================
Binary file - no diff available.

Propchange: gump/branches/Gump3/pygump/setpgrpbug/ProcessDestroyer.class
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: gump/branches/Gump3/pygump/setpgrpbug/ProcessDestroyer.java
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/pygump/setpgrpbug/ProcessDestroyer.java?rev=216132&view=auto
==============================================================================
--- gump/branches/Gump3/pygump/setpgrpbug/ProcessDestroyer.java (added)
+++ gump/branches/Gump3/pygump/setpgrpbug/ProcessDestroyer.java Wed Jul 13 02:59:02 2005
@@ -0,0 +1,216 @@
+/*
+ * Copyright  2001-2004 The Apache Software Foundation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Enumeration;
+import java.util.Vector;
+
+// MODIFIED FROM ANT CVS HEAD:
+//    http://cvs.apache.org/viewcvs.cgi/ant/src/main/org/apache/tools/ant/taskdefs/
+/**
+ * Destroys all registered <code>Process</code>es when the VM exits.
+ *
+ * @since Ant 1.5
+ */
+class ProcessDestroyer implements Runnable {
+
+    private Vector processes = new Vector();
+    // methods to register and unregister shutdown hooks
+    private Method addShutdownHookMethod;
+    private Method removeShutdownHookMethod;
+    private ProcessDestroyerImpl destroyProcessThread = null;
+
+    // whether or not this ProcessDestroyer has been registered as a
+    // shutdown hook
+    private boolean added = false;
+    // whether or not this ProcessDestroyer is currently running as
+    // shutdown hook
+    private boolean running = false;
+
+    private class ProcessDestroyerImpl extends Thread {
+        private boolean shouldDestroy = true;
+
+        public ProcessDestroyerImpl() {
+            super("ProcessDestroyer Shutdown Hook");
+        }
+        public void run() {
+            if (shouldDestroy) {
+                ProcessDestroyer.this.run();
+            }
+        }
+
+        public void setShouldDestroy(boolean shouldDestroy) {
+            this.shouldDestroy = shouldDestroy;
+        }
+    }
+
+    /**
+     * Constructs a <code>ProcessDestroyer</code> and obtains
+     * <code>Runtime.addShutdownHook()</code> and
+     * <code>Runtime.removeShutdownHook()</code> through reflection. The
+     * ProcessDestroyer manages a list of processes to be destroyed when the
+     * VM exits. If a process is added when the list is empty,
+     * this <code>ProcessDestroyer</code> is registered as a shutdown hook. If
+     * removing a process results in an empty list, the
+     * <code>ProcessDestroyer</code> is removed as a shutdown hook.
+     */
+    public ProcessDestroyer() {
+        try {
+            // check to see if the shutdown hook methods exists
+            // (support pre-JDK 1.3 VMs)
+            Class[] paramTypes = {Thread.class};
+            addShutdownHookMethod =
+                Runtime.class.getMethod("addShutdownHook", paramTypes);
+
+            removeShutdownHookMethod =
+                Runtime.class.getMethod("removeShutdownHook", paramTypes);
+            // wait to add shutdown hook as needed
+        } catch (NoSuchMethodException e) {
+            // it just won't be added as a shutdown hook... :(
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * Registers this <code>ProcessDestroyer</code> as a shutdown hook,
+     * uses reflection to ensure pre-JDK 1.3 compatibility.
+     */
+    private void addShutdownHook() {
+        if (addShutdownHookMethod != null && !running) {
+            destroyProcessThread = new ProcessDestroyerImpl();
+            Object[] args = {destroyProcessThread};
+            try {
+                addShutdownHookMethod.invoke(Runtime.getRuntime(), args);
+                added = true;
+            } catch (IllegalAccessException e) {
+                e.printStackTrace();
+            } catch (InvocationTargetException e) {
+                Throwable t = e.getTargetException();
+                if (t != null && t.getClass() == IllegalStateException.class) {
+                    // shutdown already is in progress
+                    running = true;
+                } else {
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+
+    /**
+     * Removes this <code>ProcessDestroyer</code> as a shutdown hook,
+     * uses reflection to ensure pre-JDK 1.3 compatibility
+     */
+    private void removeShutdownHook() {
+        if (removeShutdownHookMethod != null && added && !running) {
+            Object[] args = {destroyProcessThread};
+            try {
+                Boolean removed =
+                    (Boolean) removeShutdownHookMethod.invoke(
+                        Runtime.getRuntime(),
+                        args);
+                if (!removed.booleanValue()) {
+                    System.err.println("Could not remove shutdown hook");
+                }
+            } catch (IllegalAccessException e) {
+                e.printStackTrace();
+            } catch (InvocationTargetException e) {
+                Throwable t = e.getTargetException();
+                if (t != null && t.getClass() == IllegalStateException.class) {
+                    // shutdown already is in progress
+                    running = true;
+                } else {
+                    e.printStackTrace();
+                }
+            }
+            // start the hook thread, a unstarted thread may not be
+            // eligible for garbage collection
+            // Cf.: http://developer.java.sun.com/developer/bugParade/bugs/4533087.html
+            destroyProcessThread.setShouldDestroy(false);
+            destroyProcessThread.start();
+            // this should return quickly, since it basically is a NO-OP.
+            try {
+                destroyProcessThread.join(20000);
+            } catch (InterruptedException ie) {
+                // the thread didn't die in time
+                // it should not kill any processes unexpectedly
+            }
+            destroyProcessThread = null;
+            added = false;
+        }
+    }
+
+    /**
+     * Returns whether or not the ProcessDestroyer is registered as
+     * as shutdown hook
+     * @return true if this is currently added as shutdown hook
+     */
+    public boolean isAddedAsShutdownHook() {
+        return added;
+    }
+
+    /**
+     * Returns <code>true</code> if the specified <code>Process</code> was
+     * successfully added to the list of processes to destroy upon VM exit.
+     *
+     * @param   process the process to add
+     * @return  <code>true</code> if the specified <code>Process</code> was
+     *          successfully added
+     */
+    public boolean add(Process process) {
+        synchronized (processes) {
+            // if this list is empty, register the shutdown hook
+            if (processes.size() == 0) {
+                addShutdownHook();
+            }
+            processes.addElement(process);
+            return processes.contains(process);
+        }
+    }
+
+    /**
+     * Returns <code>true</code> if the specified <code>Process</code> was
+     * successfully removed from the list of processes to destroy upon VM exit.
+     *
+     * @param   process the process to remove
+     * @return  <code>true</code> if the specified <code>Process</code> was
+     *          successfully removed
+     */
+    public boolean remove(Process process) {
+        synchronized (processes) {
+            boolean processRemoved = processes.removeElement(process);
+            if (processRemoved && processes.size() == 0) {
+                removeShutdownHook();
+            }
+            return processRemoved;
+        }
+    }
+
+    /**
+     * Invoked by the VM when it is exiting.
+     */
+    public void run() {
+        synchronized (processes) {
+            running = true;
+            Enumeration e = processes.elements();
+            while (e.hasMoreElements()) {
+                ((Process) e.nextElement()).destroy();
+            }
+        }
+    }
+}

Added: gump/branches/Gump3/pygump/setpgrpbug/PumpStreamHandler.class
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/pygump/setpgrpbug/PumpStreamHandler.class?rev=216132&view=auto
==============================================================================
Binary file - no diff available.

Propchange: gump/branches/Gump3/pygump/setpgrpbug/PumpStreamHandler.class
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: gump/branches/Gump3/pygump/setpgrpbug/PumpStreamHandler.java
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/pygump/setpgrpbug/PumpStreamHandler.java?rev=216132&view=auto
==============================================================================
--- gump/branches/Gump3/pygump/setpgrpbug/PumpStreamHandler.java (added)
+++ gump/branches/Gump3/pygump/setpgrpbug/PumpStreamHandler.java Wed Jul 13 02:59:02 2005
@@ -0,0 +1,231 @@
+/*
+ * Copyright  2000-2005 The Apache Software Foundation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+// MODIFIED FROM ANT CVS HEAD:
+//    http://cvs.apache.org/viewcvs.cgi/ant/src/main/org/apache/tools/ant/taskdefs/
+/**
+ * Copies standard output and error of subprocesses to standard output and
+ * error of the parent process.
+ *
+ * @since Ant 1.2
+ */
+public class PumpStreamHandler implements ExecuteStreamHandler {
+
+    private Thread outputThread;
+    private Thread errorThread;
+    private StreamPumper inputPump;
+
+    private OutputStream out;
+    private OutputStream err;
+    private InputStream input;
+
+    /**
+     * Construct a new <CODE>PumpStreamHandler</CODE>.
+     * @param out the output <CODE>OutputStream</CODE>.
+     * @param err the error <CODE>OutputStream</CODE>.
+     * @param input the input <CODE>InputStream</CODE>.
+     */
+    public PumpStreamHandler(OutputStream out, OutputStream err,
+                             InputStream input) {
+        this.out = out;
+        this.err = err;
+        this.input = input;
+    }
+
+    /**
+     * Construct a new <CODE>PumpStreamHandler</CODE>.
+     * @param out the output <CODE>OutputStream</CODE>.
+     * @param err the error <CODE>OutputStream</CODE>.
+     */
+    public PumpStreamHandler(OutputStream out, OutputStream err) {
+        this(out, err, null);
+    }
+
+    /**
+     * Construct a new <CODE>PumpStreamHandler</CODE>.
+     * @param outAndErr the output/error <CODE>OutputStream</CODE>.
+     */
+    public PumpStreamHandler(OutputStream outAndErr) {
+        this(outAndErr, outAndErr);
+    }
+
+    /**
+     * Construct a new <CODE>PumpStreamHandler</CODE>.
+     */
+    public PumpStreamHandler() {
+        this(System.out, System.err);
+    }
+
+    /**
+     * Set the <CODE>InputStream</CODE> from which to read the
+     * standard output of the process.
+     * @param is the <CODE>InputStream</CODE>.
+     */
+    public void setProcessOutputStream(InputStream is) {
+        createProcessOutputPump(is, out);
+    }
+
+    /**
+     * Set the <CODE>InputStream</CODE> from which to read the
+     * standard error of the process.
+     * @param is the <CODE>InputStream</CODE>.
+     */
+    public void setProcessErrorStream(InputStream is) {
+        if (err != null) {
+            createProcessErrorPump(is, err);
+        }
+    }
+
+    /**
+     * Set the <CODE>OutputStream</CODE> by means of which
+     * input can be sent to the process.
+     * @param os the <CODE>OutputStream</CODE>.
+     */
+    public void setProcessInputStream(OutputStream os) {
+        if (input != null) {
+            inputPump = createInputPump(input, os, true);
+        } else {
+            try {
+                os.close();
+            } catch (IOException e) {
+                //ignore
+            }
+        }
+    }
+
+    /**
+     * Start the <CODE>Thread</CODE>s.
+     */
+    public void start() {
+        outputThread.start();
+        errorThread.start();
+        if (inputPump != null) {
+            Thread inputThread = new Thread(inputPump);
+            inputThread.setDaemon(true);
+            inputThread.start();
+        }
+    }
+
+    /**
+     * Stop pumping the streams.
+     */
+    public void stop() {
+        try {
+            outputThread.join();
+        } catch (InterruptedException e) {
+            // ignore
+        }
+        try {
+            errorThread.join();
+        } catch (InterruptedException e) {
+            // ignore
+        }
+
+        if (inputPump != null) {
+            inputPump.stop();
+        }
+
+        try {
+            err.flush();
+        } catch (IOException e) {
+            // ignore
+        }
+        try {
+            out.flush();
+        } catch (IOException e) {
+            // ignore
+        }
+    }
+
+    /**
+     * Get the error stream.
+     * @return <CODE>OutputStream</CODE>.
+     */
+    protected OutputStream getErr() {
+        return err;
+    }
+
+    /**
+     * Get the output stream.
+     * @return <CODE>OutputStream</CODE>.
+     */
+    protected OutputStream getOut() {
+        return out;
+    }
+
+    /**
+     * Create the pump to handle process output.
+     * @param is the <code>InputStream</code>.
+     * @param os the <code>OutputStream</code>.
+     */
+    protected void createProcessOutputPump(InputStream is, OutputStream os) {
+        outputThread = createPump(is, os);
+    }
+
+    /**
+     * Create the pump to handle error output.
+     * @param is the input stream to copy from.
+     * @param os the output stream to copy to.
+     */
+    protected void createProcessErrorPump(InputStream is, OutputStream os) {
+        errorThread = createPump(is, os);
+    }
+
+    /**
+     * Creates a stream pumper to copy the given input stream to the
+     * given output stream.
+     * @param is the input stream to copy from.
+     * @param os the output stream to copy to.
+     * @return a thread object that does the pumping.
+     */
+    protected Thread createPump(InputStream is, OutputStream os) {
+        return createPump(is, os, false);
+    }
+
+    /**
+     * Creates a stream pumper to copy the given input stream to the
+     * given output stream.
+     * @param is the input stream to copy from.
+     * @param os the output stream to copy to.
+     * @param closeWhenExhausted if true close the inputstream.
+     * @return a thread object that does the pumping.
+     */
+    protected Thread createPump(InputStream is, OutputStream os,
+                                boolean closeWhenExhausted) {
+        final Thread result
+            = new Thread(new StreamPumper(is, os, closeWhenExhausted));
+        result.setDaemon(true);
+        return result;
+    }
+
+    /**
+     * Creates a stream pumper to copy the given input stream to the
+     * given output stream. Used for standard input.
+     * @since Ant 1.6.3
+     */
+    /*protected*/ StreamPumper createInputPump(InputStream is, OutputStream os,
+                                boolean closeWhenExhausted) {
+        StreamPumper pumper = new StreamPumper(is, os, closeWhenExhausted);
+        pumper.setAutoflush(true);
+        return pumper;
+    }
+
+}

Added: gump/branches/Gump3/pygump/setpgrpbug/StreamPumper.class
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/pygump/setpgrpbug/StreamPumper.class?rev=216132&view=auto
==============================================================================
Binary file - no diff available.

Propchange: gump/branches/Gump3/pygump/setpgrpbug/StreamPumper.class
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: gump/branches/Gump3/pygump/setpgrpbug/StreamPumper.java
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/pygump/setpgrpbug/StreamPumper.java?rev=216132&view=auto
==============================================================================
--- gump/branches/Gump3/pygump/setpgrpbug/StreamPumper.java (added)
+++ gump/branches/Gump3/pygump/setpgrpbug/StreamPumper.java Wed Jul 13 02:59:02 2005
@@ -0,0 +1,143 @@
+/*
+ * Copyright  2000,2002-2005 The Apache Software Foundation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+// MODIFIED FROM ANT CVS HEAD:
+//    http://cvs.apache.org/viewcvs.cgi/ant/src/main/org/apache/tools/ant/taskdefs/
+/**
+ * Copies all data from an input stream to an output stream.
+ *
+ * @since Ant 1.2
+ */
+public class StreamPumper implements Runnable {
+
+    // TODO: make SIZE an instance variable.
+    // TODO: add a status flag to note if an error occurred in run.
+
+    private static final int SIZE = 128;
+    private InputStream is;
+    private OutputStream os;
+    private volatile boolean finish;
+    private volatile boolean finished;
+    private boolean closeWhenExhausted;
+    private boolean autoflush = false;
+
+    /**
+     * Create a new stream pumper.
+     *
+     * @param is input stream to read data from
+     * @param os output stream to write data to.
+     * @param closeWhenExhausted if true, the output stream will be closed when
+     *        the input is exhausted.
+     */
+    public StreamPumper(InputStream is, OutputStream os,
+                        boolean closeWhenExhausted) {
+        this.is = is;
+        this.os = os;
+        this.closeWhenExhausted = closeWhenExhausted;
+    }
+
+    /**
+     * Create a new stream pumper.
+     *
+     * @param is input stream to read data from
+     * @param os output stream to write data to.
+     */
+    public StreamPumper(InputStream is, OutputStream os) {
+        this(is, os, false);
+    }
+
+    /**
+     * Set whether data should be flushed through to the output stream.
+     * @param autoflush if true, push through data; if false, let it be buffered
+     * @since Ant 1.6.3
+     */
+    /*package*/ void setAutoflush(boolean autoflush) {
+        this.autoflush = autoflush;
+    }
+
+    /**
+     * Copies data from the input stream to the output stream.
+     *
+     * Terminates as soon as the input stream is closed or an error occurs.
+     */
+    public void run() {
+        finished = false;
+        finish = false;
+
+        final byte[] buf = new byte[SIZE];
+
+        int length;
+        try {
+            while ((length = is.read(buf)) > 0 && !finish) {
+                os.write(buf, 0, length);
+                if (autoflush) {
+                    os.flush();
+                }
+            }
+            os.flush();
+        } catch (Exception e) {
+            // ignore errors
+        } finally {
+            if (closeWhenExhausted) {
+                try {
+                    os.close();
+                } catch (IOException e) {
+                    // ignore
+                }
+            }
+            finished = true;
+            synchronized (this) {
+                notifyAll();
+            }
+        }
+    }
+
+    /**
+     * Tells whether the end of the stream has been reached.
+     * @return true is the stream has been exhausted.
+     **/
+    public boolean isFinished() {
+        return finished;
+    }
+
+    /**
+     * This method blocks until the stream pumper finishes.
+     * @see #isFinished()
+     **/
+    public synchronized void waitFor()
+        throws InterruptedException {
+        while (!isFinished()) {
+            wait();
+        }
+    }
+
+    /**
+     * Stop the pumper as soon as possible.
+     * Note that it may continue to block on the input stream
+     * but it will really stop the thread as soon as it gets EOF
+     * or any byte, and it will be marked as finished.
+     * @since Ant 1.6.3
+     */
+    /*package*/ synchronized void stop() {
+        finish = true;
+        notifyAll();
+    }
+}

Added: gump/branches/Gump3/pygump/setpgrpbug/ant-nodeps.jar
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/pygump/setpgrpbug/ant-nodeps.jar?rev=216132&view=auto
==============================================================================
Binary file - no diff available.

Propchange: gump/branches/Gump3/pygump/setpgrpbug/ant-nodeps.jar
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: gump/branches/Gump3/pygump/setpgrpbug/jaxp-api.jar
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/pygump/setpgrpbug/jaxp-api.jar?rev=216132&view=auto
==============================================================================
Binary file - no diff available.

Propchange: gump/branches/Gump3/pygump/setpgrpbug/jaxp-api.jar
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: gump/branches/Gump3/pygump/setpgrpbug/resolver.jar
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/pygump/setpgrpbug/resolver.jar?rev=216132&view=auto
==============================================================================
Binary file - no diff available.

Propchange: gump/branches/Gump3/pygump/setpgrpbug/resolver.jar
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: gump/branches/Gump3/pygump/setpgrpbug/run
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/pygump/setpgrpbug/run?rev=216132&view=auto
==============================================================================
--- gump/branches/Gump3/pygump/setpgrpbug/run (added)
+++ gump/branches/Gump3/pygump/setpgrpbug/run Wed Jul 13 02:59:02 2005
@@ -0,0 +1,28 @@
+#!/usr/bin/env bash
+
+# Attempt to reproduce http://bugs.sun.com/bugdatabase/view_bug.do;:YfiG?bug_id=4052517
+
+JAVA_HOME=/usr/lib/j2se/1.4
+JAVACMD=$JAVA_HOME/bin/java
+JAVACCMD=$JAVA_HOME/bin/javac
+PYTHONCMD=`which python2.4`
+CLASSPATH=.
+SOURCEFILES=`ls *.java`
+CLASSFILES=`ls *.class`
+MAINCLASS="Main"
+
+for i in `ls *.jar`; do
+  CLASSPATH=$CLASSPATH:./$i
+done
+
+echo JAVACMD is $JAVACMD
+echo JAVACCMD is $JAVACCMD
+echo CLASSPATH is $CLASSPATH
+
+echo Compiling...
+rm -Rf $CLASSFILES
+$JAVACCMD $SOURCEFILES
+
+echo Running...
+$PYTHONCMD run.py $JAVACMD "$MAINCLASS" "$JAVA_HOME"
+echo '...done!'

Propchange: gump/branches/Gump3/pygump/setpgrpbug/run
------------------------------------------------------------------------------
    svn:executable = *

Added: gump/branches/Gump3/pygump/setpgrpbug/run.py
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/pygump/setpgrpbug/run.py?rev=216132&view=auto
==============================================================================
--- gump/branches/Gump3/pygump/setpgrpbug/run.py (added)
+++ gump/branches/Gump3/pygump/setpgrpbug/run.py Wed Jul 13 02:59:02 2005
@@ -0,0 +1,73 @@
+#!/usr/bin/env python2.4
+
+import sys
+import signal
+import os
+from subprocess import Popen
+from subprocess import STDOUT
+import tempfile
+
+tempdir = tempfile.mkdtemp("gump_util_executor")
+
+outputfilename = os.path.join(tempdir, "log.out")
+outputfile = open(outputfilename,'w')
+processlistfilename = os.path.join(tempdir, "processlist.pids")
+
+def savepgid(filename):
+    print "setting process group.."
+    os.setpgrp()
+    f = None
+    try:
+        grp = os.getpgrp()
+        print "    Process group %s, writing to file %s" % (grp, filename)
+
+        f = open(filename,'a+')
+        f.write("%d" % grp)
+        f.write('\n')
+    finally:
+        if f:
+            try: f.close()
+            except: pass
+
+pre_exec_function = lambda: savepgid(processlistfilename)
+print "  run.py is executing %s" % sys.argv[1:]
+cmd = Popen(sys.argv[1:],shell=False,cwd=".",stdout=outputfile,stderr=STDOUT,
+            preexec_fn=pre_exec_function)
+cmd2 = Popen(sys.argv[1:],shell=False,cwd=".",stdout=outputfile,stderr=STDOUT,
+            preexec_fn=pre_exec_function)
+cmd3 = Popen(sys.argv[1:],shell=False,cwd=".",stdout=outputfile,stderr=STDOUT,
+            preexec_fn=pre_exec_function)
+cmd.wait()
+cmd2.wait()
+cmd3.wait()
+
+outputfile.close()
+outputfile = open(outputfilename,'r')
+log = unicode(outputfile.read(), 'iso-8859-1')
+outputfile.close()
+
+print "    printing log"
+print "=" * 78
+print log
+print "=" * 78
+os.unlink(outputfilename)
+
+processlistfile = open(processlistfilename, 'r')
+log = processlistfile.read()
+processlistfile.close()
+print "    pgids to kill"
+print "=" * 78
+print log
+print "=" * 78
+
+
+#import time
+#print "killing process group"
+#os.killpg(gid, signal.SIGTERM)
+#time.sleep(1)
+#os.killpg(gid, signal.SIGKILL)
+#time.sleep(1)
+
+import shutil
+shutil.rmtree(tempdir)
+

Added: gump/branches/Gump3/pygump/setpgrpbug/sax.jar
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/pygump/setpgrpbug/sax.jar?rev=216132&view=auto
==============================================================================
Binary file - no diff available.

Propchange: gump/branches/Gump3/pygump/setpgrpbug/sax.jar
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: gump/branches/Gump3/pygump/setpgrpbug/which.jar
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/pygump/setpgrpbug/which.jar?rev=216132&view=auto
==============================================================================
Binary file - no diff available.

Propchange: gump/branches/Gump3/pygump/setpgrpbug/which.jar
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: gump/branches/Gump3/pygump/setpgrpbug/xercesImpl.jar
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/pygump/setpgrpbug/xercesImpl.jar?rev=216132&view=auto
==============================================================================
Binary file - no diff available.

Propchange: gump/branches/Gump3/pygump/setpgrpbug/xercesImpl.jar
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: gump/branches/Gump3/pygump/setpgrpbug/xml-apis.jar
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/pygump/setpgrpbug/xml-apis.jar?rev=216132&view=auto
==============================================================================
Binary file - no diff available.

Propchange: gump/branches/Gump3/pygump/setpgrpbug/xml-apis.jar
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream