This is the mail archive of the
java-patches@gcc.gnu.org
mailing list for the Java project.
Patch: RFC: fix ProcessBuilder; windows help needed
- From: Tom Tromey <tromey at redhat dot com>
- To: GCJ-patches <java-patches at gcc dot gnu dot org>
- Date: 02 Feb 2007 15:13:45 -0700
- Subject: Patch: RFC: fix ProcessBuilder; windows help needed
- Reply-to: tromey at redhat dot com
I'm still testing this patch. I'll check it in once I'm done.
During the last Classpath merge I must have stubbed out
ProcessBuilder. This patch fixes that and removes a divergence of
ours in the process.
One problem with this patch is that I did not update the Windows
port. I added the needed method argument, but it does not do
anything. I would appreciate it if someone could fix this.
Tom
Index: ChangeLog
from Tom Tromey <tromey@redhat.com>
* sources.am, Makefile.in: Rebuilt.
* scripts/makemake.tcl (emit_package_rule): Don't omit
VMProcess.java.
* Makefile.am (nat_source_files): Added natVMProcess.cc.
(inner_nat_headers): Added ImmediateEOFInputStream.h.
* gcj/javaprims.h: Regenerated.
* java/lang/System.java (EnvironmentMap): Now package-private.
(EnvironmentMap(Map)): New constructor.
(EnvironmentMap.put): New method.
* java/lang/natWin32Process.cc (startProcess): Update.
* java/lang/Win32Process.java (Win32Process): Added 'redirect'
argument.
(startProcess): Likewise.
* java/lang/EcosProcess.java (EcosProcess): Added 'redirect'
argument.
* java/lang/natPosixProcess.cc (nativeSpawn): Handle redirection.
* java/lang/PosixProcess.java (redirect): New field.
(PosixProcess): Added 'redirect' argument.
* java/lang/natRuntime.cc (execInternal): Added 'redirect'
argument to Process creation.
* java/lang/natVMProcess.cc: New file.
* java/lang/ProcessBuilder.java: Removed.
* java/lang/VMProcess.java: New file.
Index: scripts/makemake.tcl
===================================================================
--- scripts/makemake.tcl (revision 121470)
+++ scripts/makemake.tcl (working copy)
@@ -285,7 +285,7 @@
# Object and Class are special cases due to an apparent compiler
# bug. Process is a special case because we don't build all
# concrete implementations of Process on all platforms.
- set omit "| tr ' ' '\\n' | fgrep -v Object.class | fgrep -v Class.class | grep -v '\[^/\]Process' "
+ set omit "| tr ' ' '\\n' | fgrep -v Object.class | fgrep -v Class.class | egrep -v '\(Ecos\|Posix\|Win32\)Process' "
} else {
set omit ""
}
Index: gcj/javaprims.h
===================================================================
--- gcj/javaprims.h (revision 121470)
+++ gcj/javaprims.h (working copy)
@@ -1,7 +1,7 @@
// javaprims.h - Main external header file for libgcj. -*- c++ -*-
-/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
Free Software Foundation
This file is part of libgcj.
@@ -248,6 +248,7 @@
class VMCompiler;
class VMDouble;
class VMFloat;
+ class VMProcess;
class VMThrowable;
class VerifyError;
class VirtualMachineError;
Index: java/lang/Win32Process.java
===================================================================
--- java/lang/Win32Process.java (revision 121470)
+++ java/lang/Win32Process.java (working copy)
@@ -1,6 +1,6 @@
// Win32Process.java - Subclass of Process for Win32 systems.
-/* Copyright (C) 2002, 2003, 2006 Free Software Foundation
+/* Copyright (C) 2002, 2003, 2006, 2007 Free Software Foundation
This file is part of libgcj.
@@ -51,9 +51,8 @@
public native int waitFor () throws InterruptedException;
- public Win32Process (String[] progarray,
- String[] envp,
- File dir)
+ public Win32Process (String[] progarray, String[] envp, File dir,
+ boolean redirect)
throws IOException
{
for (int i = 0; i < progarray.length; i++)
@@ -64,7 +63,7 @@
progarray[i] = "\"" + s + "\"";
}
- startProcess (progarray, envp, dir);
+ startProcess (progarray, envp, dir, redirect);
}
// The standard streams (stdin, stdout and stderr, respectively)
@@ -81,8 +80,9 @@
private native boolean hasExited ();
private native void startProcess (String[] progarray,
- String[] envp,
- File dir)
+ String[] envp,
+ File dir,
+ boolean redirect)
throws IOException;
private native void cleanup ();
}
Index: java/lang/VMProcess.java
===================================================================
--- java/lang/VMProcess.java (revision 0)
+++ java/lang/VMProcess.java (revision 0)
@@ -0,0 +1,68 @@
+/* java.lang.VMProcess -- VM implementation of java.lang.ProcessBuilder
+ Copyright (C) 2007 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.lang;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+final class VMProcess
+{
+ static native Process nativeExec(String[] cmd, String[] env,
+ File dir, boolean redirect)
+ throws IOException;
+
+ static Process exec(List<String> cmd, Map<String, String> env,
+ File dir, boolean redirect) throws IOException
+ {
+ String[] acmd = (String[]) cmd.toArray(new String[cmd.size()]);
+ String[] aenv = new String[env.size()];
+
+ int i = 0;
+ Iterator iter = env.entrySet().iterator();
+ while (iter.hasNext())
+ {
+ Map.Entry entry = (Map.Entry) iter.next();
+ aenv[i++] = entry.getKey() + "=" + entry.getValue();
+ }
+
+ return nativeExec(acmd, aenv, dir, redirect);
+ }
+}
Index: java/lang/System.java
===================================================================
--- java/lang/System.java (revision 121470)
+++ java/lang/System.java (working copy)
@@ -1,5 +1,5 @@
/* System.java -- useful methods to interface with the system
- Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -827,7 +827,7 @@
*
* @author Andrew John Hughes (gnu_andrew@member.fsf.org)
*/
- private static class EnvironmentMap
+ static class EnvironmentMap
extends HashMap<String,String>
{
@@ -853,8 +853,21 @@
{
super();
}
-
+
/**
+ * Constructs a new <code>EnvironmentMap</code> containing
+ * the contents of the specified map.
+ *
+ * @param m the map to be added to this.
+ * @throws NullPointerException if a key or value is null.
+ * @throws ClassCastException if a key or value is not a String.
+ */
+ EnvironmentMap(Map<String,String> m)
+ {
+ super(m);
+ }
+
+ /**
* Blocks queries containing a null key or one which is not
* of type <code>String</code>. All other queries
* are forwarded to the superclass.
@@ -938,8 +951,33 @@
keys = new EnvironmentSet(super.keySet());
return keys;
}
-
+
/**
+ * Associates the given key to the given value. If the
+ * map already contains the key, its value is replaced.
+ * The map does not accept null keys or values, or keys
+ * and values not of type {@link String}.
+ *
+ * @param key the key to map.
+ * @param value the value to be mapped.
+ * @return the previous value of the key, or null if there was no mapping
+ * @throws NullPointerException if a key or value is null.
+ * @throws ClassCastException if a key or value is not a String.
+ */
+ public String put(String key, String value)
+ {
+ if (key == null)
+ throw new NullPointerException("A new key is null.");
+ if (value == null)
+ throw new NullPointerException("A new value is null.");
+ if (!(key instanceof String))
+ throw new ClassCastException("A new key is not a String.");
+ if (!(value instanceof String))
+ throw new ClassCastException("A new value is not a String.");
+ return super.put(key, value);
+ }
+
+ /**
* Removes a key-value pair from the map. The queried key may not
* be null or of a type other than a <code>String</code>.
*
Index: java/lang/natVMProcess.cc
===================================================================
--- java/lang/natVMProcess.cc (revision 0)
+++ java/lang/natVMProcess.cc (revision 0)
@@ -0,0 +1,34 @@
+// natVMProcess.cc - native code for ProcessBuilder
+
+/* Copyright (C) 2007 Free Software Foundation
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+#include <config.h>
+
+#include <gcj/cni.h>
+#include <jvm.h>
+
+#include <platform.h>
+
+#include <java/lang/VMProcess.h>
+#include <java/lang/Process.h>
+#include <java/io/File.h>
+
+// It is convenient and safe to simply include all of these.
+#include <java/lang/Win32Process.h>
+#include <java/lang/EcosProcess.h>
+#include <java/lang/PosixProcess.h>
+
+::java::lang::Process *
+java::lang::VMProcess::nativeExec (jstringArray cmd,
+ jstringArray env,
+ ::java::io::File *dir,
+ jboolean redirect)
+{
+ return new _Jv_platform_process (cmd, env, dir, redirect);
+}
Index: java/lang/EcosProcess.java
===================================================================
--- java/lang/EcosProcess.java (revision 121470)
+++ java/lang/EcosProcess.java (working copy)
@@ -1,6 +1,6 @@
// EcosProcess.java - Subclass of Process for eCos systems.
-/* Copyright (C) 1998, 1999, 2006 Free Software Foundation
+/* Copyright (C) 1998, 1999, 2006, 2007 Free Software Foundation
This file is part of libgcj.
@@ -51,9 +51,8 @@
return 0;
}
- public EcosProcess (String[] progarray,
- String[] envp,
- File dir)
+ public EcosProcess (String[] progarray, String[] envp, File dir,
+ boolean redirect)
throws IOException
{
throw new IOException ("eCos processes unimplemented");
Index: java/lang/PosixProcess.java
===================================================================
--- java/lang/PosixProcess.java (revision 121470)
+++ java/lang/PosixProcess.java (working copy)
@@ -1,5 +1,5 @@
// PosixProcess.java - Subclass of Process for POSIX systems.
-/* Copyright (C) 1998, 1999, 2004, 2006 Free Software Foundation
+/* Copyright (C) 1998, 1999, 2004, 2006, 2007 Free Software Foundation
This file is part of libgcj.
@@ -349,8 +349,8 @@
*/
private native void nativeSpawn();
- PosixProcess(String[] progarray, String[] envp, File dir)
- throws IOException
+ PosixProcess(String[] progarray, String[] envp, File dir, boolean redirect)
+ throws IOException
{
// Check to ensure there is something to run, and avoid
// dereferencing null pointers in native code.
@@ -360,6 +360,7 @@
this.progarray = progarray;
this.envp = envp;
this.dir = dir;
+ this.redirect = redirect;
// Start a ProcessManager if there is not one already running.
synchronized (queueLock)
@@ -414,6 +415,7 @@
private String[] progarray;
private String[] envp;
private File dir;
+ private boolean redirect;
/** Set by the ProcessManager on problems starting. */
private Throwable exception;
Index: java/lang/natWin32Process.cc
===================================================================
--- java/lang/natWin32Process.cc (revision 121470)
+++ java/lang/natWin32Process.cc (working copy)
@@ -1,6 +1,6 @@
// natWin32Process.cc - Native side of Win32 process code.
-/* Copyright (C) 2003, 2006 Free Software Foundation
+/* Copyright (C) 2003, 2006, 2007 Free Software Foundation
This file is part of libgcj.
@@ -210,8 +210,9 @@
void
java::lang::Win32Process::startProcess (jstringArray progarray,
- jstringArray envp,
- java::io::File *dir)
+ jstringArray envp,
+ java::io::File *dir,
+ jboolean redirect)
{
using namespace java::io;
Index: java/lang/natPosixProcess.cc
===================================================================
--- java/lang/natPosixProcess.cc (revision 121470)
+++ java/lang/natPosixProcess.cc (working copy)
@@ -1,6 +1,6 @@
// natPosixProcess.cc - Native side of POSIX process code.
-/* Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004, 2005, 2006 Free Software Foundation
+/* Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation
This file is part of libgcj.
@@ -41,6 +41,7 @@
#include <java/io/FileOutputStream.h>
#include <java/io/IOException.h>
#include <java/lang/OutOfMemoryError.h>
+#include <java/lang/PosixProcess$EOFInputStream.h>
using gnu::java::nio::channels::FileChannelImpl;
@@ -231,7 +232,7 @@
try
{
// Transform arrays to native form.
- args = (char **) _Jv_Malloc ((progarray->length + 1) * sizeof (char *));
+ args = (char **) _Jv_Malloc ((progarray->length + 1) * sizeof (char *));
// Initialize so we can gracefully recover.
jstring *elts = elements (progarray);
@@ -262,23 +263,30 @@
path = new_string (dir->getPath ());
// Create pipes for I/O. MSGP is for communicating exec()
- // status.
- if (pipe (inp) || pipe (outp) || pipe (errp) || pipe (msgp)
+ // status. If redirecting stderr to stdout, we don't need to
+ // create the ERRP pipe.
+ if (pipe (inp) || pipe (outp) || pipe (msgp)
|| fcntl (msgp[1], F_SETFD, FD_CLOEXEC))
- throw new IOException (JvNewStringUTF (strerror (errno)));
+ throw new IOException (JvNewStringUTF (strerror (errno)));
+ if (! redirect && pipe (errp))
+ throw new IOException (JvNewStringUTF (strerror (errno)));
// We create the streams before forking. Otherwise if we had an
// error while creating the streams we would have run the child
// with no way to communicate with it.
- errorStream =
- new FileInputStream (new
- FileChannelImpl (errp[0], FileChannelImpl::READ));
- inputStream =
- new FileInputStream (new
- FileChannelImpl (inp[0], FileChannelImpl::READ));
- outputStream =
- new FileOutputStream (new FileChannelImpl (outp[1],
- FileChannelImpl::WRITE));
+ if (redirect)
+ errorStream = PosixProcess$EOFInputStream::instance;
+ else
+ errorStream =
+ new FileInputStream (new
+ FileChannelImpl (errp[0],
+ FileChannelImpl::READ));
+ inputStream =
+ new FileInputStream (new
+ FileChannelImpl (inp[0], FileChannelImpl::READ));
+ outputStream =
+ new FileOutputStream (new FileChannelImpl (outp[1],
+ FileChannelImpl::WRITE));
// We don't use vfork() because that would cause the local
// environment to be set by the child.
@@ -319,14 +327,17 @@
// We ignore errors from dup2 because they should never occur.
dup2 (outp[0], 0);
dup2 (inp[1], 1);
- dup2 (errp[1], 2);
+ dup2 (redirect ? inp[1] : errp[1], 2);
// Use close and not myclose -- we're in the child, and we
// aren't worried about the possible race condition.
close (inp[0]);
close (inp[1]);
- close (errp[0]);
- close (errp[1]);
+ if (! redirect)
+ {
+ close (errp[0]);
+ close (errp[1]);
+ }
close (outp[0]);
close (outp[1]);
close (msgp[0]);
@@ -362,8 +373,11 @@
myclose (outp[0]);
myclose (inp[1]);
- myclose (errp[1]);
- myclose (msgp[1]);
+ if (! redirect)
+ {
+ myclose (errp[1]);
+ myclose (msgp[1]);
+ }
char c;
int r = read (msgp[0], &c, 1);
@@ -406,7 +420,7 @@
{
if (errorStream != NULL)
errorStream->close ();
- else
+ else if (! redirect)
myclose (errp[0]);
}
catch (java::lang::Throwable *ignore)
@@ -417,10 +431,11 @@
// the use of myclose.
myclose (outp[0]);
myclose (inp[1]);
- myclose (errp[1]);
+ if (! redirect)
+ myclose (errp[1]);
myclose (msgp[1]);
- exception = thrown;
+ exception = thrown;
}
myclose (msgp[0]);
@@ -430,6 +445,7 @@
{
fcntl (outp[1], F_SETFD, FD_CLOEXEC);
fcntl (inp[0], F_SETFD, FD_CLOEXEC);
- fcntl (errp[0], F_SETFD, FD_CLOEXEC);
+ if (! redirect)
+ fcntl (errp[0], F_SETFD, FD_CLOEXEC);
}
}
Index: java/lang/ProcessBuilder.java
===================================================================
--- java/lang/ProcessBuilder.java (revision 121470)
+++ java/lang/ProcessBuilder.java (working copy)
@@ -1,118 +0,0 @@
-/* ProcessBuilder.java - Represent spawned system process
- Copyright (C) 2005, 2006 Free Software Foundation, Inc.
-
-This file is part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-
-package java.lang;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-
-public final class ProcessBuilder
-{
- private File directory = new File(System.getProperty("user.dir"));
- private List<String> command;
- // FIXME: make a copy.
- private Map<String, String> environment = System.getenv();
- private boolean redirect = false;
-
- public ProcessBuilder(List<String> command)
- {
- this.command = command;
- }
-
- public ProcessBuilder(String... command)
- {
- this.command = Arrays.asList(command);
- }
-
- public List<String> command()
- {
- return command;
- }
-
- public ProcessBuilder command(List<String> command)
- {
- this.command = command;
- return this;
- }
-
- public ProcessBuilder command(String... command)
- {
- this.command = Arrays.asList(command);
- return this;
- }
-
- public File directory()
- {
- return directory;
- }
-
- public ProcessBuilder directory(File directory)
- {
- this.directory = directory;
- return this;
- }
-
- public Map<String, String> environment()
- {
- return environment;
- }
-
- public boolean redirectErrorStream()
- {
- return redirect;
- }
-
- public ProcessBuilder redirectErrorStream(boolean redirect)
- {
- this.redirect = redirect;
- return this;
- }
-
- public Process start() throws IOException
- {
- SecurityManager sm = SecurityManager.current; // Be thread-safe!
- if (sm != null)
- sm.checkExec(command.get(0));
- // return VMProcess.exec(command, environment, directory, redirect);
- // FIXME
- return null;
- }
-}
Index: java/lang/natRuntime.cc
===================================================================
--- java/lang/natRuntime.cc (revision 121470)
+++ java/lang/natRuntime.cc (working copy)
@@ -1,6 +1,6 @@
// natRuntime.cc - Implementation of native side of Runtime class.
-/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation
+/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation
This file is part of libgcj.
@@ -297,7 +297,7 @@
jstringArray env,
java::io::File *dir)
{
- return new _Jv_platform_process (cmd, env, dir);
+ return new _Jv_platform_process (cmd, env, dir, false);
}
jint
Index: Makefile.am
===================================================================
--- Makefile.am (revision 121470)
+++ Makefile.am (working copy)
@@ -399,6 +399,7 @@
java/nio/DirectByteBufferImpl$$ReadWrite.h \
java/nio/channels/Pipe$$SinkChannel.h \
java/nio/channels/Pipe$$SourceChannel.h \
+ java/lang/VMProcess$ImmediateEOFInputStream.h \
java/lang/reflect/Proxy$$ProxyData.h \
java/lang/reflect/Proxy$$ProxyType.h \
gnu/java/net/PlainSocketImpl$$SocketInputStream.h \
@@ -864,6 +865,7 @@
java/lang/natThread.cc \
java/lang/natThreadLocal.cc \
java/lang/natVMClassLoader.cc \
+java/lang/natVMProcess.cc \
java/lang/natVMThrowable.cc \
java/lang/ref/natReference.cc \
java/lang/reflect/natArray.cc \