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