summaryrefslogtreecommitdiff
path: root/libjava
diff options
context:
space:
mode:
authortromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4>2003-02-10 23:52:56 +0000
committertromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4>2003-02-10 23:52:56 +0000
commit277c2165b1000176eaa04f22c940cf46df44c7dc (patch)
treed76d0682ab2c7f55130f40b4332a102e90d49551 /libjava
parent0c1515d70f292a71dc29661e6a169abedd0fc455 (diff)
downloadgcc-277c2165b1000176eaa04f22c940cf46df44c7dc.tar.gz
2003-02-10 Ranjit Mathew <rmathew@hotmail.com>
* java/lang/Win32Process.java (destroy): Declare as native. (hasExited): New native method. (exitValue): Define. (getErrorStream): Likewise. (getInputStream): Likewise. (getOutputStream): Likewise. (waitFor): Declare as native. (startProcess): New native method. (cleanup): Likewise. (ConcreteProcess): Define. (outputStream, inputStream, errorStream): New members. (procHandle, exitCode): Likewise. * java/lang/natWin32Process.cc (java::lang::ConcreteProcess::cleanup): Define. (java::lang::ConcreteProcess::destroy): Likewise. (java::lang::ConcreteProcess::hasExited): Likewise. (java::lang::ConcreteProcess::waitFor): Likewise. (new_string): Likewise. (java::lang::ConcreteProcess::startProcess): Likewise. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@62657 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libjava')
-rw-r--r--libjava/ChangeLog23
-rw-r--r--libjava/java/lang/Win32Process.java52
-rw-r--r--libjava/java/lang/natWin32Process.cc294
3 files changed, 349 insertions, 20 deletions
diff --git a/libjava/ChangeLog b/libjava/ChangeLog
index 0f9454d7781..f5ec059558f 100644
--- a/libjava/ChangeLog
+++ b/libjava/ChangeLog
@@ -1,3 +1,26 @@
+2003-02-10 Ranjit Mathew <rmathew@hotmail.com>
+
+ * java/lang/Win32Process.java (destroy): Declare as native.
+ (hasExited): New native method.
+ (exitValue): Define.
+ (getErrorStream): Likewise.
+ (getInputStream): Likewise.
+ (getOutputStream): Likewise.
+ (waitFor): Declare as native.
+ (startProcess): New native method.
+ (cleanup): Likewise.
+ (ConcreteProcess): Define.
+ (outputStream, inputStream, errorStream): New members.
+ (procHandle, exitCode): Likewise.
+
+ * java/lang/natWin32Process.cc
+ (java::lang::ConcreteProcess::cleanup): Define.
+ (java::lang::ConcreteProcess::destroy): Likewise.
+ (java::lang::ConcreteProcess::hasExited): Likewise.
+ (java::lang::ConcreteProcess::waitFor): Likewise.
+ (new_string): Likewise.
+ (java::lang::ConcreteProcess::startProcess): Likewise.
+
2003-02-10 Raif S. Naffah <raif@fl.net.au>
* java/math/BigInteger.java:
diff --git a/libjava/java/lang/Win32Process.java b/libjava/java/lang/Win32Process.java
index 72911d2961b..b1c7e027379 100644
--- a/libjava/java/lang/Win32Process.java
+++ b/libjava/java/lang/Win32Process.java
@@ -1,6 +1,6 @@
// Win32Process.java - Subclass of Process for Win32 systems.
-/* Copyright (C) 2002 Free Software Foundation
+/* Copyright (C) 2002, 2003 Free Software Foundation
This file is part of libgcj.
@@ -22,51 +22,63 @@ import java.io.IOException;
// This is entirely internal to our implementation.
-// NOTE: when this is implemented, we'll need to add
-// HANDLE_FLAG_INHERIT in FileDescriptor and other places, to make
-// sure that file descriptors aren't inherited by the child process.
-// See _Jv_platform_close_on_exec.
-
// This file is copied to `ConcreteProcess.java' before compilation.
// Hence the class name apparently does not match the file name.
final class ConcreteProcess extends Process
{
- public void destroy ()
- {
- throw new Error("not implemented");
- }
-
+ public native void destroy ();
+
+ public native boolean hasExited ();
+
public int exitValue ()
{
- throw new Error("not implemented");
+ if (! hasExited ())
+ throw new IllegalThreadStateException ("Process has not exited");
+
+ return exitCode;
}
public InputStream getErrorStream ()
{
- throw new Error("not implemented");
+ return errorStream;
}
public InputStream getInputStream ()
{
- throw new Error("not implemented");
+ return inputStream;
}
public OutputStream getOutputStream ()
{
- throw new Error("not implemented");
+ return outputStream;
}
- public int waitFor () throws InterruptedException
- {
- throw new Error("not implemented");
- }
+ public native int waitFor () throws InterruptedException;
+
+ public native void startProcess (String[] progarray,
+ String[] envp,
+ File dir)
+ throws IOException;
+
+ public native void cleanup ();
public ConcreteProcess (String[] progarray,
String[] envp,
File dir)
throws IOException
{
- throw new IOException("not implemented");
+ startProcess (progarray, envp, dir);
}
+ // The standard streams (stdin, stdout and stderr, respectively)
+ // of the child as seen by the parent process.
+ private OutputStream outputStream;
+ private InputStream inputStream;
+ private InputStream errorStream;
+
+ // Handle to the child process - cast to HANDLE before use.
+ private int procHandle;
+
+ // Exit code of the child if it has exited.
+ private int exitCode;
}
diff --git a/libjava/java/lang/natWin32Process.cc b/libjava/java/lang/natWin32Process.cc
index e69de29bb2d..38e6f919174 100644
--- a/libjava/java/lang/natWin32Process.cc
+++ b/libjava/java/lang/natWin32Process.cc
@@ -0,0 +1,294 @@
+// natWin32Process.cc - Native side of Win32 process code.
+
+/* Copyright (C) 2003 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 <stdio.h>
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+// Conflicts with the definition in "java/lang/reflect/Modifier.h"
+#undef STRICT
+
+#include <gcj/cni.h>
+#include <jvm.h>
+
+#include <java/lang/ConcreteProcess.h>
+#include <java/lang/IllegalThreadStateException.h>
+#include <java/lang/InterruptedException.h>
+#include <java/lang/NullPointerException.h>
+#include <java/lang/Thread.h>
+#include <java/io/File.h>
+#include <java/io/FileDescriptor.h>
+#include <java/io/FileInputStream.h>
+#include <java/io/FileOutputStream.h>
+#include <java/io/IOException.h>
+#include <java/lang/OutOfMemoryError.h>
+
+void
+java::lang::ConcreteProcess::cleanup (void)
+{
+ if (inputStream != NULL)
+ {
+ inputStream->close ();
+ inputStream = NULL;
+ }
+
+ if (outputStream != NULL)
+ {
+ outputStream->close ();
+ outputStream = NULL;
+ }
+
+ if (errorStream != NULL)
+ {
+ errorStream->close ();
+ errorStream = NULL;
+ }
+}
+
+void
+java::lang::ConcreteProcess::destroy (void)
+{
+ if (! hasExited ())
+ {
+ // Kill it forcibly and assign an (arbitrary) exit code of 0.
+ TerminateProcess ((HANDLE) procHandle, 0);
+ exitCode = 0;
+
+ cleanup ();
+ }
+}
+
+jboolean
+java::lang::ConcreteProcess::hasExited (void)
+{
+ DWORD exitStatus;
+
+ if (GetExitCodeProcess ((HANDLE) procHandle, &exitStatus) != 0)
+ {
+ // NOTE: STILL_ACTIVE is defined as "259" by Win32 - if the
+ // child actually exits with this return code, we have a
+ // problem here. See MSDN documentation on GetExitCodeProcess( ).
+
+ if (exitStatus == STILL_ACTIVE)
+ return false;
+ else
+ {
+ cleanup ();
+ exitCode = exitStatus;
+ return true;
+ }
+ }
+ else
+ return true;
+}
+
+jint
+java::lang::ConcreteProcess::waitFor (void)
+{
+ if (! hasExited ())
+ {
+ DWORD exitStatus = 0UL;
+
+ // FIXME: The wait should be interruptible.
+ WaitForSingleObject ((HANDLE) procHandle, INFINITE);
+
+ GetExitCodeProcess ((HANDLE) procHandle, &exitStatus);
+ exitCode = exitStatus;
+
+ cleanup ();
+ }
+
+ return exitCode;
+}
+
+static char *
+new_string (jstring string)
+{
+ jsize s = _Jv_GetStringUTFLength (string);
+ char *buf = (char *) _Jv_Malloc (s + 1);
+ _Jv_GetStringUTFRegion (string, 0, s, buf);
+ buf[s] = '\0';
+ return buf;
+}
+
+void
+java::lang::ConcreteProcess::startProcess (jstringArray progarray,
+ jstringArray envp,
+ java::io::File *dir)
+{
+ using namespace java::io;
+
+ procHandle = (jint) INVALID_HANDLE_VALUE;
+
+ // Reconstruct the command line.
+ jstring *elts = elements (progarray);
+
+ int cmdLineLen = 0;
+
+ for (int i = 0; i < progarray->length; ++i)
+ cmdLineLen += (_Jv_GetStringUTFLength (elts[i]) + 1);
+
+ char *cmdLine = (char *) _Jv_Malloc (cmdLineLen + 1);
+
+ int j = 0;
+ for (int i = 0; i < progarray->length; ++i)
+ {
+ jsize s = _Jv_GetStringUTFLength (elts[i]);
+ _Jv_GetStringUTFRegion (elts[i], 0, s, (cmdLine + j));
+
+ j += s;
+ *(cmdLine + j) = ' ';
+ j++;
+ }
+ *(cmdLine + j) = '\0';
+
+ // Get the environment, if any.
+ char *env = NULL;
+ if (envp)
+ {
+ elts = elements (envp);
+
+ int envLen = 0;
+ for (int i = 0; i < envp->length; ++i)
+ envLen += (_Jv_GetStringUTFLength (elts[i]) + 1);
+
+ env = (char *) _Jv_Malloc (envLen + 1);
+
+ int j = 0;
+ for (int i = 0; i < envp->length; ++i)
+ {
+ jsize s = _Jv_GetStringUTFLength (elts[i]);
+ _Jv_GetStringUTFRegion (elts[i], 0, s, (env + j));
+
+ j += s;
+ *(env + j) = '\0';
+ j++;
+ }
+ *(env + j) = '\0';
+ }
+
+ // Get the working directory path, if specified.
+ char *wdir = NULL;
+ if (dir != NULL)
+ wdir = new_string (dir->getPath ());
+
+ errorStream = NULL;
+ inputStream = NULL;
+ outputStream = NULL;
+
+ java::lang::Throwable *exc = NULL;
+
+ try
+ {
+ // We create anonymous pipes to communicate with the child
+ // on each of standard streams.
+
+ HANDLE cldStdInRd, cldStdInWr;
+ HANDLE cldStdOutRd, cldStdOutWr;
+ HANDLE cldStdErrRd, cldStdErrWr;
+
+ SECURITY_ATTRIBUTES sAttrs;
+
+ // Explicitly allow the handles to the pipes to be inherited.
+ sAttrs.nLength = sizeof (SECURITY_ATTRIBUTES);
+ sAttrs.bInheritHandle = 1;
+ sAttrs.lpSecurityDescriptor = NULL;
+
+
+ char tmpBuff[64];
+ if (CreatePipe (&cldStdInRd, &cldStdInWr, &sAttrs, 0) == 0)
+ {
+ sprintf (tmpBuff,
+ "Error creating stdin pipe (Win32 Error Code: %lu)",
+ GetLastError ());
+ throw new IOException (JvNewStringLatin1 (tmpBuff));
+ }
+
+ if (CreatePipe (&cldStdOutRd, &cldStdOutWr, &sAttrs, 0) == 0)
+ {
+ sprintf (tmpBuff,
+ "Error creating stdout pipe (Win32 Error Code: %lu)",
+ GetLastError ());
+ throw new IOException (JvNewStringLatin1 (tmpBuff));
+ }
+
+ if (CreatePipe (&cldStdErrRd, &cldStdErrWr, &sAttrs, 0) == 0)
+ {
+ sprintf (tmpBuff,
+ "Error creating stderr pipe (Win32 Error Code: %lu)",
+ GetLastError ());
+ throw new IOException (JvNewStringLatin1 (tmpBuff));
+ }
+
+ outputStream = new FileOutputStream
+ (new FileDescriptor ((jint) cldStdInWr));
+ inputStream = new FileInputStream
+ (new FileDescriptor ((jint) cldStdOutRd));
+ errorStream = new FileInputStream
+ (new FileDescriptor ((jint) cldStdErrRd));
+
+ // Now create the child process.
+ PROCESS_INFORMATION pi;
+ STARTUPINFO si;
+
+ ZeroMemory (&pi, sizeof (PROCESS_INFORMATION));
+
+ ZeroMemory (&si, sizeof (STARTUPINFO));
+ si.cb = sizeof (STARTUPINFO);
+
+ // Explicitly specify the handles to the standard streams.
+ si.dwFlags |= STARTF_USESTDHANDLES;
+
+ si.hStdInput = cldStdInRd;
+ si.hStdOutput = cldStdOutWr;
+ si.hStdError = cldStdErrWr;
+
+ if (CreateProcess (NULL,
+ cmdLine,
+ NULL,
+ NULL,
+ 1,
+ 0,
+ env,
+ wdir,
+ &si,
+ &pi) == 0)
+ {
+ sprintf (tmpBuff,
+ "Error creating child process (Win32 Error Code: %lu)",
+ GetLastError ());
+ throw new IOException (JvNewStringLatin1 (tmpBuff));
+ }
+
+ procHandle = (jint ) pi.hProcess;
+
+ // Close the wrong ends (for the parent) of the pipes.
+ CloseHandle (cldStdInRd);
+ CloseHandle (cldStdOutWr);
+ CloseHandle (cldStdErrWr);
+
+ _Jv_Free (cmdLine);
+ if (env != NULL)
+ _Jv_Free (env);
+ if (wdir != NULL)
+ _Jv_Free (wdir);
+ }
+ catch (java::lang::Throwable *thrown)
+ {
+ cleanup ();
+ exc = thrown;
+ }
+
+ if (exc != NULL)
+ throw exc;
+}