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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libjava/] [java/] [lang/] [natWin32Process.cc] - Blame information for rev 14

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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