Win32Process.java (destroy): Declare as native.
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. From-SVN: r62657
This commit is contained in:
parent
17e39e5c61
commit
d6a2d36ee7
@ -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:
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user