source: trunk/gcc/libjava/java/lang/natWin32Process.cc

Last change on this file was 1392, checked in by bird, 21 years ago

This commit was generated by cvs2svn to compensate for changes in r1391,
which included commits to RCS files with non-trunk default branches.

  • Property cvs2svn:cvs-rev set to 1.1.1.2
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 7.3 KB
Line 
1// natWin32Process.cc - Native side of Win32 process code.
2
3/* Copyright (C) 2003 Free Software Foundation
4
5 This file is part of libgcj.
6
7This software is copyrighted work licensed under the terms of the
8Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
9details. */
10
11#include <config.h>
12
13#include <stdio.h>
14
15#define WIN32_LEAN_AND_MEAN
16#include <windows.h>
17
18// Conflicts with the definition in "java/lang/reflect/Modifier.h"
19#undef STRICT
20
21#include <gcj/cni.h>
22#include <jvm.h>
23
24#include <java/lang/ConcreteProcess.h>
25#include <java/lang/IllegalThreadStateException.h>
26#include <java/lang/InterruptedException.h>
27#include <java/lang/NullPointerException.h>
28#include <java/lang/Thread.h>
29#include <java/io/File.h>
30#include <java/io/FileDescriptor.h>
31#include <java/io/FileInputStream.h>
32#include <java/io/FileOutputStream.h>
33#include <java/io/IOException.h>
34#include <java/lang/OutOfMemoryError.h>
35
36void
37java::lang::ConcreteProcess::cleanup (void)
38{
39 if (inputStream != NULL)
40 {
41 inputStream->close ();
42 inputStream = NULL;
43 }
44
45 if (outputStream != NULL)
46 {
47 outputStream->close ();
48 outputStream = NULL;
49 }
50
51 if (errorStream != NULL)
52 {
53 errorStream->close ();
54 errorStream = NULL;
55 }
56}
57
58void
59java::lang::ConcreteProcess::destroy (void)
60{
61 if (! hasExited ())
62 {
63 // Kill it forcibly and assign an (arbitrary) exit code of 0.
64 TerminateProcess ((HANDLE) procHandle, 0);
65 exitCode = 0;
66
67 cleanup ();
68 }
69}
70
71jboolean
72java::lang::ConcreteProcess::hasExited (void)
73{
74 DWORD exitStatus;
75
76 if (GetExitCodeProcess ((HANDLE) procHandle, &exitStatus) != 0)
77 {
78 // NOTE: STILL_ACTIVE is defined as "259" by Win32 - if the
79 // child actually exits with this return code, we have a
80 // problem here. See MSDN documentation on GetExitCodeProcess( ).
81
82 if (exitStatus == STILL_ACTIVE)
83 return false;
84 else
85 {
86 cleanup ();
87 exitCode = exitStatus;
88 return true;
89 }
90 }
91 else
92 return true;
93}
94
95jint
96java::lang::ConcreteProcess::waitFor (void)
97{
98 if (! hasExited ())
99 {
100 DWORD exitStatus = 0UL;
101
102 // FIXME: The wait should be interruptible.
103 WaitForSingleObject ((HANDLE) procHandle, INFINITE);
104
105 GetExitCodeProcess ((HANDLE) procHandle, &exitStatus);
106 exitCode = exitStatus;
107
108 cleanup ();
109 }
110
111 return exitCode;
112}
113
114static char *
115new_string (jstring string)
116{
117 jsize s = _Jv_GetStringUTFLength (string);
118 char *buf = (char *) _Jv_Malloc (s + 1);
119 _Jv_GetStringUTFRegion (string, 0, s, buf);
120 buf[s] = '\0';
121 return buf;
122}
123
124void
125java::lang::ConcreteProcess::startProcess (jstringArray progarray,
126 jstringArray envp,
127 java::io::File *dir)
128{
129 using namespace java::io;
130
131 procHandle = (jint) INVALID_HANDLE_VALUE;
132
133 // Reconstruct the command line.
134 jstring *elts = elements (progarray);
135
136 int cmdLineLen = 0;
137
138 for (int i = 0; i < progarray->length; ++i)
139 cmdLineLen += (_Jv_GetStringUTFLength (elts[i]) + 3);
140
141 char *cmdLine = (char *) _Jv_Malloc (cmdLineLen + 1);
142 char *cmdLineCurPos = cmdLine;
143
144 for (int i = 0; i < progarray->length; ++i)
145 {
146 if (i > 0)
147 *cmdLineCurPos++ = ' ';
148 *cmdLineCurPos++ = '\"';
149 jsize s = _Jv_GetStringUTFLength (elts[i]);
150 _Jv_GetStringUTFRegion (elts[i], 0, s, cmdLineCurPos);
151 cmdLineCurPos += s;
152 *cmdLineCurPos++ = '\"';
153 }
154 *cmdLineCurPos = '\0';
155
156 // Get the environment, if any.
157 char *env = NULL;
158 if (envp)
159 {
160 elts = elements (envp);
161
162 int envLen = 0;
163 for (int i = 0; i < envp->length; ++i)
164 envLen += (_Jv_GetStringUTFLength (elts[i]) + 1);
165
166 env = (char *) _Jv_Malloc (envLen + 1);
167
168 int j = 0;
169 for (int i = 0; i < envp->length; ++i)
170 {
171 jsize s = _Jv_GetStringUTFLength (elts[i]);
172 _Jv_GetStringUTFRegion (elts[i], 0, s, (env + j));
173
174 j += s;
175 *(env + j) = '\0';
176 j++;
177 }
178 *(env + j) = '\0';
179 }
180
181 // Get the working directory path, if specified.
182 char *wdir = NULL;
183 if (dir != NULL)
184 wdir = new_string (dir->getPath ());
185
186 errorStream = NULL;
187 inputStream = NULL;
188 outputStream = NULL;
189
190 java::lang::Throwable *exc = NULL;
191
192 try
193 {
194 // We create anonymous pipes to communicate with the child
195 // on each of standard streams.
196
197 HANDLE cldStdInRd, cldStdInWr;
198 HANDLE cldStdOutRd, cldStdOutWr;
199 HANDLE cldStdErrRd, cldStdErrWr;
200
201 SECURITY_ATTRIBUTES sAttrs;
202
203 // Explicitly allow the handles to the pipes to be inherited.
204 sAttrs.nLength = sizeof (SECURITY_ATTRIBUTES);
205 sAttrs.bInheritHandle = 1;
206 sAttrs.lpSecurityDescriptor = NULL;
207
208
209 char tmpBuff[64];
210 if (CreatePipe (&cldStdInRd, &cldStdInWr, &sAttrs, 0) == 0)
211 {
212 sprintf (tmpBuff,
213 "Error creating stdin pipe (Win32 Error Code: %lu)",
214 GetLastError ());
215 throw new IOException (JvNewStringLatin1 (tmpBuff));
216 }
217
218 if (CreatePipe (&cldStdOutRd, &cldStdOutWr, &sAttrs, 0) == 0)
219 {
220 sprintf (tmpBuff,
221 "Error creating stdout pipe (Win32 Error Code: %lu)",
222 GetLastError ());
223 throw new IOException (JvNewStringLatin1 (tmpBuff));
224 }
225
226 if (CreatePipe (&cldStdErrRd, &cldStdErrWr, &sAttrs, 0) == 0)
227 {
228 sprintf (tmpBuff,
229 "Error creating stderr pipe (Win32 Error Code: %lu)",
230 GetLastError ());
231 throw new IOException (JvNewStringLatin1 (tmpBuff));
232 }
233
234 outputStream = new FileOutputStream
235 (new FileDescriptor ((jint) cldStdInWr));
236 inputStream = new FileInputStream
237 (new FileDescriptor ((jint) cldStdOutRd));
238 errorStream = new FileInputStream
239 (new FileDescriptor ((jint) cldStdErrRd));
240
241 // Now create the child process.
242 PROCESS_INFORMATION pi;
243 STARTUPINFO si;
244
245 ZeroMemory (&pi, sizeof (PROCESS_INFORMATION));
246
247 ZeroMemory (&si, sizeof (STARTUPINFO));
248 si.cb = sizeof (STARTUPINFO);
249
250 // Explicitly specify the handles to the standard streams.
251 si.dwFlags |= STARTF_USESTDHANDLES;
252
253 si.hStdInput = cldStdInRd;
254 si.hStdOutput = cldStdOutWr;
255 si.hStdError = cldStdErrWr;
256
257 if (CreateProcess (NULL,
258 cmdLine,
259 NULL,
260 NULL,
261 1,
262 0,
263 env,
264 wdir,
265 &si,
266 &pi) == 0)
267 {
268 sprintf (tmpBuff,
269 "Error creating child process (Win32 Error Code: %lu)",
270 GetLastError ());
271 throw new IOException (JvNewStringLatin1 (tmpBuff));
272 }
273
274 procHandle = (jint ) pi.hProcess;
275
276 // Close the wrong ends (for the parent) of the pipes.
277 CloseHandle (cldStdInRd);
278 CloseHandle (cldStdOutWr);
279 CloseHandle (cldStdErrWr);
280
281 _Jv_Free (cmdLine);
282 if (env != NULL)
283 _Jv_Free (env);
284 if (wdir != NULL)
285 _Jv_Free (wdir);
286 }
287 catch (java::lang::Throwable *thrown)
288 {
289 cleanup ();
290 exc = thrown;
291 }
292
293 if (exc != NULL)
294 throw exc;
295}
Note: See TracBrowser for help on using the repository browser.