OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [java/] [lang/] [natWin32Process.cc] - Blame information for rev 830

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 758 jeremybenn
// natWin32Process.cc - Native side of Win32 process code.
2
 
3
/* Copyright (C) 2003, 2006, 2007  Free Software Foundation
4
 
5
   This file is part of libgcj.
6
 
7
This software is copyrighted work licensed under the terms of the
8
Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
9
details.  */
10
 
11
#include <config.h>
12
#include <platform.h>
13
 
14
// Conflicts with the definition in "java/lang/reflect/Modifier.h"
15
#undef STRICT
16
 
17
#include <java/lang/Win32Process.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>
28
#include <java/lang/Win32Process$EOFInputStream.h>
29
#include <gnu/java/nio/channels/FileChannelImpl.h>
30
 
31
using gnu::java::nio::channels::FileChannelImpl;
32
 
33
void
34
java::lang::Win32Process::cleanup (void)
35
{
36
  // FIXME:
37
  // We used to close the input, output and
38
  // error streams here, but we can't do that
39
  // because the caller also has the right
40
  // to close these and FileInputStream and FileOutputStream
41
  // scream if you attempt to close() them twice. Presently,
42
  // we use _Jv_platform_close_on_exec, which is similar
43
  // to the POSIX approach.
44
  //
45
  // What I wanted to do is have private nested
46
  // classes in Win32Process which extend FileInputStream
47
  // and FileOutputStream, respectively, but override
48
  // close() to permit multiple calls to close(). This
49
  // led to class header and platform configury issues
50
  // that I didn't feel like dealing with. However,
51
  // this approach could conceivably be a good multiplatform
52
  // one since delaying the pipe close until process
53
  // termination could be wasteful if many child processes
54
  // are spawned within the parent process' lifetime.
55
  inputStream = NULL;
56
  outputStream = NULL;
57
  errorStream = NULL;
58
 
59
  if (procHandle)
60
    {
61
      CloseHandle((HANDLE) procHandle);
62
      procHandle = (jint) INVALID_HANDLE_VALUE;
63
    }
64
}
65
 
66
void
67
java::lang::Win32Process::destroy (void)
68
{
69
  if (! hasExited ())
70
    {
71
      // Kill it forcibly and assign an (arbitrary) exit code of 0.
72
      TerminateProcess ((HANDLE) procHandle, 0);
73
      exitCode = 0;
74
 
75
      cleanup ();
76
    }
77
}
78
 
79
jboolean
80
java::lang::Win32Process::hasExited (void)
81
{
82
  DWORD exitStatus;
83
 
84
  if (GetExitCodeProcess ((HANDLE) procHandle, &exitStatus) != 0)
85
    {
86
      // NOTE: STILL_ACTIVE is defined as "259" by Win32 - if the
87
      // child actually exits with this return code, we have a
88
      // problem here. See MSDN documentation on GetExitCodeProcess( ).
89
 
90
      if (exitStatus == STILL_ACTIVE)
91
        return false;
92
      else
93
        {
94
          cleanup ();
95
          exitCode = exitStatus;
96
          return true;
97
        }
98
    }
99
  else
100
    return true;
101
}
102
 
103
jint
104
java::lang::Win32Process::waitFor (void)
105
{
106
  if (! hasExited ())
107
    {
108
      DWORD exitStatus = 0UL;
109
 
110
      // Set up our waitable objects array
111
      // - 0: the handle to the process we just launched
112
      // - 1: our thread's interrupt event
113
      HANDLE arh[2];
114
      arh[0] = (HANDLE) procHandle;
115
      arh[1] = _Jv_Win32GetInterruptEvent ();
116
      DWORD rval = WaitForMultipleObjects (2, arh, 0, INFINITE);
117
 
118
      // Use the returned value from WaitForMultipleObjects
119
      // instead of our thread's interrupt_flag to test for
120
      // thread interruption. See the comment for
121
      // _Jv_Win32GetInterruptEvent().
122
      bool bInterrupted = rval == (WAIT_OBJECT_0 + 1);
123
 
124
      if (bInterrupted)
125
        {
126
          // Querying this forces a reset our thread's interrupt flag.
127
          Thread::interrupted();
128
 
129
          cleanup ();
130
          throw new InterruptedException ();
131
        }
132
 
133
      GetExitCodeProcess ((HANDLE) procHandle, &exitStatus);
134
      exitCode = exitStatus;
135
 
136
      cleanup ();
137
    }
138
 
139
  return exitCode;
140
}
141
 
142
 
143
// Helper class for creating and managing the pipes
144
// used for I/O redirection for child processes.
145
class ChildProcessPipe
146
{
147
public:
148
  // Indicates from the child process' point of view
149
  // whether the pipe is for reading or writing.
150
  enum EType {INPUT, OUTPUT, DUMMY};
151
 
152
  ChildProcessPipe(EType eType);
153
  ~ChildProcessPipe();
154
 
155
  // Returns a pipe handle suitable for use by the parent process
156
  HANDLE getParentHandle();
157
 
158
  // Returns a pipe handle suitable for use by the child process.
159
  HANDLE getChildHandle();
160
 
161
private:
162
  EType m_eType;
163
  HANDLE m_hRead, m_hWrite;
164
};
165
 
166
ChildProcessPipe::ChildProcessPipe(EType eType):
167
  m_eType(eType), m_hRead(0), m_hWrite(0)
168
{
169
  if (eType == DUMMY)
170
    return;
171
 
172
  SECURITY_ATTRIBUTES sAttrs;
173
 
174
  // Explicitly allow the handles to the pipes to be inherited.
175
  sAttrs.nLength = sizeof (SECURITY_ATTRIBUTES);
176
  sAttrs.bInheritHandle = 1;
177
  sAttrs.lpSecurityDescriptor = NULL;
178
 
179
  if (CreatePipe (&m_hRead, &m_hWrite, &sAttrs, 0) == 0)
180
    {
181
      DWORD dwErrorCode = GetLastError ();
182
      throw new java::io::IOException (
183
        _Jv_WinStrError (_T("Error creating pipe"), dwErrorCode));
184
    }
185
 
186
  // If this is the read end of the child, we need
187
  // to make the parent write end non-inheritable. Similarly,
188
  // if this is the write end of the child, we need to make
189
  // the parent read end non-inheritable. If we didn't
190
  // do this, the child would inherit these ends and we wouldn't
191
  // be able to close them from our end. For full details,
192
  // do a Google search on "Q190351".
193
  HANDLE& rhStd = m_eType==INPUT ? m_hWrite : m_hRead;
194
  _Jv_platform_close_on_exec (rhStd);
195
}
196
 
197
ChildProcessPipe::~ChildProcessPipe()
198
{
199
  // Close the parent end of the pipe. This
200
  // destructor is called after the child process
201
  // has been spawned.
202
  if (m_eType != DUMMY)
203
    CloseHandle(getChildHandle());
204
}
205
 
206
HANDLE ChildProcessPipe::getParentHandle()
207
{
208
  return m_eType==INPUT ? m_hWrite : m_hRead;
209
}
210
 
211
HANDLE ChildProcessPipe::getChildHandle()
212
{
213
  return m_eType==INPUT ? m_hRead : m_hWrite;
214
}
215
 
216
void
217
java::lang::Win32Process::startProcess (jstringArray progarray,
218
                                        jstringArray envp,
219
                                        java::io::File *dir,
220
                                        jboolean redirect)
221
{
222
  using namespace java::io;
223
 
224
  procHandle = (jint) INVALID_HANDLE_VALUE;
225
 
226
  // Reconstruct the command line.
227
  jstring *elts = elements (progarray);
228
 
229
  int cmdLineLen = 0;
230
 
231
  for (int i = 0; i < progarray->length; ++i)
232
    cmdLineLen += (elts[i]->length() + 1);
233
 
234
  LPTSTR cmdLine = (LPTSTR) _Jv_Malloc ((cmdLineLen + 1) * sizeof(TCHAR));
235
  LPTSTR cmdLineCurPos = cmdLine;
236
 
237
  for (int i = 0; i < progarray->length; ++i)
238
    {
239
      if (i > 0)
240
        *cmdLineCurPos++ = _T(' ');
241
 
242
      jint len = elts[i]->length();
243
      JV_TEMP_STRING_WIN32(thiselt, elts[i]);
244
      _tcscpy(cmdLineCurPos, thiselt);
245
      cmdLineCurPos += len;
246
    }
247
  *cmdLineCurPos = _T('\0');
248
 
249
  // Get the environment, if any.
250
  LPTSTR env = NULL;
251
  if (envp)
252
    {
253
      elts = elements (envp);
254
 
255
      int envLen = 0;
256
      for (int i = 0; i < envp->length; ++i)
257
        envLen += (elts[i]->length() + 1);
258
 
259
      env = (LPTSTR) _Jv_Malloc ((envLen + 1) * sizeof(TCHAR));
260
 
261
      int j = 0;
262
      for (int i = 0; i < envp->length; ++i)
263
        {
264
          jint len = elts[i]->length();
265
 
266
          JV_TEMP_STRING_WIN32(thiselt, elts[i]);
267
          _tcscpy(env + j, thiselt);
268
 
269
          j += len;
270
 
271
          // Skip past the null terminator that _tcscpy just inserted.
272
          j++;
273
        }
274
      *(env + j) = _T('\0');
275
    }
276
 
277
  // Get the working directory path, if specified.
278
  JV_TEMP_STRING_WIN32 (wdir, dir ? dir->getPath () : 0);
279
 
280
  errorStream = NULL;
281
  inputStream = NULL;
282
  outputStream = NULL;
283
 
284
  java::lang::Throwable *exc = NULL;
285
 
286
  try
287
    {
288
      // We create anonymous pipes to communicate with the child
289
      // on each of standard streams.
290
      ChildProcessPipe aChildStdIn(ChildProcessPipe::INPUT);
291
      ChildProcessPipe aChildStdOut(ChildProcessPipe::OUTPUT);
292
      ChildProcessPipe aChildStdErr(redirect ? ChildProcessPipe::DUMMY
293
                                    : ChildProcessPipe::OUTPUT);
294
 
295
      outputStream = new FileOutputStream (new FileChannelImpl (
296
                           (jint) aChildStdIn.getParentHandle (),
297
                           FileChannelImpl::WRITE));
298
      inputStream = new FileInputStream (new FileChannelImpl (
299
                           (jint) aChildStdOut.getParentHandle (),
300
                           FileChannelImpl::READ));
301
      if (redirect)
302
        errorStream = Win32Process$EOFInputStream::instance;
303
      else
304
        errorStream = new FileInputStream (new FileChannelImpl (
305
                           (jint) aChildStdErr.getParentHandle (),
306
                           FileChannelImpl::READ));
307
 
308
      // Now create the child process.
309
      PROCESS_INFORMATION pi;
310
      STARTUPINFO si;
311
 
312
      ZeroMemory (&pi, sizeof (PROCESS_INFORMATION));
313
 
314
      ZeroMemory (&si, sizeof (STARTUPINFO));
315
      si.cb = sizeof (STARTUPINFO);
316
 
317
      // Explicitly specify the handles to the standard streams.
318
      si.dwFlags |= STARTF_USESTDHANDLES;
319
 
320
      si.hStdInput = aChildStdIn.getChildHandle();
321
      si.hStdOutput = aChildStdOut.getChildHandle();
322
      si.hStdError = redirect ? aChildStdOut.getChildHandle()
323
                              : aChildStdErr.getChildHandle();
324
 
325
      // Spawn the process. CREATE_NO_WINDOW only applies when
326
      // starting a console application; it suppresses the
327
      // creation of a console window. This flag is ignored on
328
      // Win9X.
329
 
330
      if (CreateProcess (NULL,
331
                         cmdLine,
332
                         NULL,
333
                         NULL,
334
                         1,
335
                         CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT,
336
                         env,
337
                         wdir,
338
                         &si,
339
                         &pi) == 0)
340
        {
341
          DWORD dwErrorCode = GetLastError ();
342
          throw new IOException (
343
            _Jv_WinStrError (_T("Error creating child process"), dwErrorCode));
344
        }
345
 
346
      procHandle = (jint ) pi.hProcess;
347
 
348
      _Jv_Free (cmdLine);
349
      if (env != NULL)
350
        _Jv_Free (env);
351
    }
352
  catch (java::lang::Throwable *thrown)
353
    {
354
      cleanup ();
355
      exc = thrown;
356
    }
357
 
358
  if (exc != NULL)
359
    throw exc;
360
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.