1 // natWin32Process.cc - Native side of Win32 process code.
3 /* Copyright (C) 2003 Free Software Foundation
5 This file is part of libgcj.
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
14 // Conflicts with the definition in "java/lang/reflect/Modifier.h"
17 #include <java/lang/ConcreteProcess.h>
18 #include <java/lang/IllegalThreadStateException.h>
19 #include <java/lang/InterruptedException.h>
20 #include <java/lang/NullPointerException.h>
21 #include <java/lang/Thread.h>
22 #include <java/io/File.h>
23 #include <java/io/FileDescriptor.h>
24 #include <java/io/FileInputStream.h>
25 #include <java/io/FileOutputStream.h>
26 #include <java/io/IOException.h>
27 #include <java/lang/OutOfMemoryError.h>
30 java::lang::ConcreteProcess::cleanup (void)
32 if (inputStream != NULL)
34 inputStream->close ();
38 if (outputStream != NULL)
40 outputStream->close ();
44 if (errorStream != NULL)
46 errorStream->close ();
52 java::lang::ConcreteProcess::destroy (void)
56 // Kill it forcibly and assign an (arbitrary) exit code of 0.
57 TerminateProcess ((HANDLE) procHandle, 0);
65 java::lang::ConcreteProcess::hasExited (void)
69 if (GetExitCodeProcess ((HANDLE) procHandle, &exitStatus) != 0)
71 // NOTE: STILL_ACTIVE is defined as "259" by Win32 - if the
72 // child actually exits with this return code, we have a
73 // problem here. See MSDN documentation on GetExitCodeProcess( ).
75 if (exitStatus == STILL_ACTIVE)
80 exitCode = exitStatus;
89 java::lang::ConcreteProcess::waitFor (void)
93 DWORD exitStatus = 0UL;
95 // FIXME: The wait should be interruptible.
96 WaitForSingleObject ((HANDLE) procHandle, INFINITE);
98 GetExitCodeProcess ((HANDLE) procHandle, &exitStatus);
99 exitCode = exitStatus;
108 java::lang::ConcreteProcess::startProcess (jstringArray progarray,
112 using namespace java::io;
114 procHandle = (jint) INVALID_HANDLE_VALUE;
116 // Reconstruct the command line.
117 jstring *elts = elements (progarray);
121 for (int i = 0; i < progarray->length; ++i)
122 cmdLineLen += (_Jv_GetStringUTFLength (elts[i]) + 1);
124 char *cmdLine = (char *) _Jv_Malloc (cmdLineLen + 1);
125 char *cmdLineCurPos = cmdLine;
127 for (int i = 0; i < progarray->length; ++i)
130 *cmdLineCurPos++ = ' ';
131 jsize s = _Jv_GetStringUTFLength (elts[i]);
132 _Jv_GetStringUTFRegion (elts[i], 0, s, cmdLineCurPos);
135 *cmdLineCurPos = '\0';
137 // Get the environment, if any.
141 elts = elements (envp);
144 for (int i = 0; i < envp->length; ++i)
145 envLen += (_Jv_GetStringUTFLength (elts[i]) + 1);
147 env = (char *) _Jv_Malloc (envLen + 1);
150 for (int i = 0; i < envp->length; ++i)
152 jsize s = _Jv_GetStringUTFLength (elts[i]);
153 _Jv_GetStringUTFRegion (elts[i], 0, s, (env + j));
162 // Get the working directory path, if specified.
163 JV_TEMP_UTF_STRING (wdir, dir ? dir->getPath () : 0);
169 java::lang::Throwable *exc = NULL;
173 // We create anonymous pipes to communicate with the child
174 // on each of standard streams.
176 HANDLE cldStdInRd, cldStdInWr;
177 HANDLE cldStdOutRd, cldStdOutWr;
178 HANDLE cldStdErrRd, cldStdErrWr;
180 SECURITY_ATTRIBUTES sAttrs;
182 // Explicitly allow the handles to the pipes to be inherited.
183 sAttrs.nLength = sizeof (SECURITY_ATTRIBUTES);
184 sAttrs.bInheritHandle = 1;
185 sAttrs.lpSecurityDescriptor = NULL;
188 if (CreatePipe (&cldStdInRd, &cldStdInWr, &sAttrs, 0) == 0)
190 DWORD dwErrorCode = GetLastError ();
191 throw new IOException (_Jv_WinStrError ("Error creating stdin pipe",
195 if (CreatePipe (&cldStdOutRd, &cldStdOutWr, &sAttrs, 0) == 0)
197 DWORD dwErrorCode = GetLastError ();
198 throw new IOException (_Jv_WinStrError ("Error creating stdout pipe",
202 if (CreatePipe (&cldStdErrRd, &cldStdErrWr, &sAttrs, 0) == 0)
204 DWORD dwErrorCode = GetLastError ();
205 throw new IOException (_Jv_WinStrError ("Error creating stderr pipe",
209 outputStream = new FileOutputStream
210 (new FileDescriptor ((jint) cldStdInWr));
211 inputStream = new FileInputStream
212 (new FileDescriptor ((jint) cldStdOutRd));
213 errorStream = new FileInputStream
214 (new FileDescriptor ((jint) cldStdErrRd));
216 // Now create the child process.
217 PROCESS_INFORMATION pi;
220 ZeroMemory (&pi, sizeof (PROCESS_INFORMATION));
222 ZeroMemory (&si, sizeof (STARTUPINFO));
223 si.cb = sizeof (STARTUPINFO);
225 // Explicitly specify the handles to the standard streams.
226 si.dwFlags |= STARTF_USESTDHANDLES;
228 si.hStdInput = cldStdInRd;
229 si.hStdOutput = cldStdOutWr;
230 si.hStdError = cldStdErrWr;
232 if (CreateProcess (NULL,
243 DWORD dwErrorCode = GetLastError ();
244 throw new IOException (
245 _Jv_WinStrError ("Error creating child process", dwErrorCode));
248 procHandle = (jint ) pi.hProcess;
250 // Close the wrong ends (for the parent) of the pipes.
251 CloseHandle (cldStdInRd);
252 CloseHandle (cldStdOutWr);
253 CloseHandle (cldStdErrWr);
259 catch (java::lang::Throwable *thrown)