2008-05-04 Doug Kwan <dougkwan@google.com>
[official-gcc.git] / libjava / java / lang / natPosixProcess.cc
blobfbd3f6a0a1b1a1da555544b06cc48011e3b2e395
1 // natPosixProcess.cc - Native side of POSIX process code.
3 /* Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004, 2005, 2006, 2007
4 Free Software Foundation
6 This file is part of libgcj.
8 This software is copyrighted work licensed under the terms of the
9 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
10 details. */
12 #include <config.h>
14 #ifdef HAVE_UNISTD_H
15 #include <unistd.h>
16 #endif
17 #include <errno.h>
18 #include <fcntl.h>
19 #include <sys/types.h>
20 #include <sys/wait.h>
21 #ifdef HAVE_SYS_TIME_H
22 #include <sys/time.h>
23 #endif
24 #ifdef HAVE_SYS_RESOURCE_H
25 #include <sys/resource.h>
26 #endif
27 #include <signal.h>
28 #include <string.h>
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <unistd.h>
32 #include <pthread.h>
34 #include <posix.h>
35 #include <posix-threads.h>
36 #include <jvm.h>
38 #include <java/lang/PosixProcess$ProcessManager.h>
39 #include <java/lang/PosixProcess.h>
40 #include <java/lang/IllegalThreadStateException.h>
41 #include <java/lang/InternalError.h>
42 #include <java/lang/InterruptedException.h>
43 #include <java/lang/NullPointerException.h>
44 #include <java/lang/Thread.h>
45 #include <java/io/File.h>
46 #include <java/io/FileDescriptor.h>
47 #include <gnu/java/nio/channels/FileChannelImpl.h>
48 #include <java/io/FileInputStream.h>
49 #include <java/io/FileOutputStream.h>
50 #include <java/io/IOException.h>
51 #include <java/lang/OutOfMemoryError.h>
52 #include <java/lang/PosixProcess$EOFInputStream.h>
54 using gnu::java::nio::channels::FileChannelImpl;
55 using namespace java::lang;
57 extern char **environ;
59 static char *
60 new_string (jstring string)
62 jsize s = _Jv_GetStringUTFLength (string);
63 char *buf = (char *) _Jv_Malloc (s + 1);
64 _Jv_GetStringUTFRegion (string, 0, string->length(), buf);
65 buf[s] = '\0';
66 return buf;
69 static void
70 cleanup (char **args, char **env, char *path)
72 if (args != NULL)
74 for (int i = 0; args[i] != NULL; ++i)
75 _Jv_Free (args[i]);
76 _Jv_Free (args);
78 if (env != NULL)
80 for (int i = 0; env[i] != NULL; ++i)
81 _Jv_Free (env[i]);
82 _Jv_Free (env);
84 if (path != NULL)
85 _Jv_Free (path);
88 // This makes our error handling a bit simpler and it lets us avoid
89 // thread bugs where we close a possibly-reopened file descriptor for
90 // a second time.
91 static void
92 myclose (int &fd)
94 if (fd != -1)
95 close (fd);
96 fd = -1;
99 namespace
101 struct ProcessManagerInternal
103 int pipe_ends[2];
104 struct sigaction old_sigaction;
109 // There has to be a signal handler in order to be able to
110 // sigwait() on SIGCHLD. The information passed is ignored as it
111 // will be recovered by the waitpid() call.
112 static void
113 #ifdef SA_SIGINFO
114 sigchld_handler (int sig, siginfo_t *si, void *third)
115 #else
116 sigchld_handler (int sig)
117 #endif
119 if (PosixProcess$ProcessManager::nativeData != NULL)
121 ProcessManagerInternal *pmi =
122 (ProcessManagerInternal *)PosixProcess$ProcessManager::nativeData;
123 char c = 0;
124 ::write(pmi->pipe_ends[1], &c, 1);
125 if (pmi->old_sigaction.sa_handler != SIG_DFL
126 && pmi->old_sigaction.sa_handler != SIG_IGN)
128 #ifdef SA_SIGINFO
129 if ((pmi->old_sigaction.sa_flags & SA_SIGINFO) != 0)
130 pmi->old_sigaction.sa_sigaction(sig, si, third);
131 else
132 #endif
133 (*pmi->old_sigaction.sa_handler)(sig);
139 // Get ready to enter the main reaper thread loop.
140 void
141 java::lang::PosixProcess$ProcessManager::init ()
143 // The nativeData is static to avoid races installing the signal
144 // handler in the case that it is chained.
145 if (nativeData == NULL )
147 ProcessManagerInternal *pmi =
148 (ProcessManagerInternal *)JvAllocBytes(sizeof(ProcessManagerInternal));
150 if (0 != ::pipe(pmi->pipe_ends))
151 goto error;
153 // Make writing non-blocking so that the signal handler will
154 // never block.
155 int fl = ::fcntl(pmi->pipe_ends[1], F_GETFL);
156 ::fcntl(pmi->pipe_ends[1], F_SETFL, fl | O_NONBLOCK);
158 nativeData = (::gnu::gcj::RawDataManaged *)pmi;
160 // SIGCHLD is blocked in all threads in posix-threads.cc.
161 // Setup the SIGCHLD handler.
162 struct sigaction sa;
163 memset (&sa, 0, sizeof (sa));
165 #ifdef SA_SIGINFO
166 sa.sa_sigaction = sigchld_handler;
167 // We only want signals when the things exit.
168 sa.sa_flags = SA_NOCLDSTOP | SA_SIGINFO;
169 #else
170 sa.sa_handler = sigchld_handler;
171 // We only want signals when the things exit.
172 sa.sa_flags = SA_NOCLDSTOP;
173 #endif
175 if (-1 == sigaction (SIGCHLD, &sa, &pmi->old_sigaction))
176 goto error;
178 // All OK.
179 return;
181 error:
182 throw new InternalError (JvNewStringUTF (strerror (errno)));
185 void
186 java::lang::PosixProcess$ProcessManager::waitForSignal ()
188 // Wait for SIGCHLD
189 _Jv_UnBlockSigchld();
190 ProcessManagerInternal *pmi = (ProcessManagerInternal *)nativeData;
192 // Try to read multiple (64) notifications in one go.
193 char c[64];
194 ::read(pmi->pipe_ends[0], c, sizeof (c));
196 _Jv_BlockSigchld();
198 return;
201 jboolean java::lang::PosixProcess$ProcessManager::reap (PosixProcess *p)
203 pid_t rv;
205 // Try to get the return code from the child process.
206 int status;
207 rv = ::waitpid ((pid_t)p->pid, &status, WNOHANG);
208 if (rv == -1)
209 throw new InternalError (JvNewStringUTF (strerror (errno)));
211 if (rv == 0)
212 return false; // No children to wait for.
214 JvSynchronize sync (p);
215 p->status = WIFEXITED (status) ? WEXITSTATUS (status) : -1;
216 p->state = PosixProcess::STATE_TERMINATED;
217 p->processTerminationCleanup();
218 p->notifyAll ();
219 return true;
222 void
223 java::lang::PosixProcess$ProcessManager::signalReaper ()
225 ProcessManagerInternal *pmi = (ProcessManagerInternal *)nativeData;
226 char c = 0;
227 ::write(pmi->pipe_ends[1], &c, 1);
228 // Ignore errors. If EPIPE the reaper has already exited.
231 void
232 java::lang::PosixProcess::nativeDestroy ()
234 int c = ::kill ((pid_t) pid, SIGKILL);
235 if (c == 0)
236 return;
237 // kill() failed.
238 throw new InternalError (JvNewStringUTF (strerror (errno)));
241 void
242 java::lang::PosixProcess::nativeSpawn ()
244 using namespace java::io;
246 // Initialize all locals here to make cleanup simpler.
247 char **args = NULL;
248 char **env = NULL;
249 char *path = NULL;
250 int inp[2], outp[2], errp[2], msgp[2];
251 inp[0] = -1;
252 inp[1] = -1;
253 outp[0] = -1;
254 outp[1] = -1;
255 errp[0] = -1;
256 errp[1] = -1;
257 msgp[0] = -1;
258 msgp[1] = -1;
259 errorStream = NULL;
260 inputStream = NULL;
261 outputStream = NULL;
265 // Transform arrays to native form.
266 args = (char **) _Jv_Malloc ((progarray->length + 1) * sizeof (char *));
268 // Initialize so we can gracefully recover.
269 jstring *elts = elements (progarray);
270 for (int i = 0; i <= progarray->length; ++i)
271 args[i] = NULL;
273 for (int i = 0; i < progarray->length; ++i)
274 args[i] = new_string (elts[i]);
275 args[progarray->length] = NULL;
277 if (envp)
279 bool need_path = true;
280 bool need_ld_library_path = true;
281 int i;
283 // Preserve PATH and LD_LIBRARY_PATH unless specified
284 // explicitly. We need three extra slots. Potentially PATH
285 // and LD_LIBRARY_PATH will be added plus the NULL
286 // termination.
287 env = (char **) _Jv_Malloc ((envp->length + 3) * sizeof (char *));
288 elts = elements (envp);
290 // Initialize so we can gracefully recover.
291 for (i = 0; i < envp->length + 3; ++i)
292 env[i] = NULL;
294 for (i = 0; i < envp->length; ++i)
296 env[i] = new_string (elts[i]);
297 if (!strncmp (env[i], "PATH=", sizeof("PATH=")))
298 need_path = false;
299 if (!strncmp (env[i], "LD_LIBRARY_PATH=",
300 sizeof("LD_LIBRARY_PATH=")))
301 need_ld_library_path = false;
304 if (need_path)
306 char *path_val = getenv ("PATH");
307 if (path_val)
309 env[i] = (char *) _Jv_Malloc (strlen (path_val) +
310 sizeof("PATH=") + 1);
311 strcpy (env[i], "PATH=");
312 strcat (env[i], path_val);
313 i++;
316 if (need_ld_library_path)
318 char *path_val = getenv ("LD_LIBRARY_PATH");
319 if (path_val)
321 env[i] =
322 (char *) _Jv_Malloc (strlen (path_val) +
323 sizeof("LD_LIBRARY_PATH=") + 1);
324 strcpy (env[i], "LD_LIBRARY_PATH=");
325 strcat (env[i], path_val);
326 i++;
329 env[i] = NULL;
332 // We allocate this here because we can't call malloc() after
333 // the fork.
334 if (dir != NULL)
335 path = new_string (dir->getPath ());
337 // Create pipes for I/O. MSGP is for communicating exec()
338 // status. If redirecting stderr to stdout, we don't need to
339 // create the ERRP pipe.
340 if (pipe (inp) || pipe (outp) || pipe (msgp)
341 || fcntl (msgp[1], F_SETFD, FD_CLOEXEC))
342 throw new IOException (JvNewStringUTF (strerror (errno)));
343 if (! redirect && pipe (errp))
344 throw new IOException (JvNewStringUTF (strerror (errno)));
346 // We create the streams before forking. Otherwise if we had an
347 // error while creating the streams we would have run the child
348 // with no way to communicate with it.
349 if (redirect)
350 errorStream = PosixProcess$EOFInputStream::instance;
351 else
352 errorStream =
353 new FileInputStream (new
354 FileChannelImpl (errp[0],
355 FileChannelImpl::READ));
356 inputStream =
357 new FileInputStream (new
358 FileChannelImpl (inp[0], FileChannelImpl::READ));
359 outputStream =
360 new FileOutputStream (new FileChannelImpl (outp[1],
361 FileChannelImpl::WRITE));
363 // We don't use vfork() because that would cause the local
364 // environment to be set by the child.
366 // Use temporary for fork result to avoid dirtying an extra page.
367 pid_t pid_tmp;
368 if ((pid_tmp = fork ()) == -1)
369 throw new IOException (JvNewStringUTF (strerror (errno)));
371 if (pid_tmp == 0)
373 // Child process, so remap descriptors, chdir and exec.
374 if (envp)
375 environ = env;
377 // We ignore errors from dup2 because they should never occur.
378 dup2 (outp[0], 0);
379 dup2 (inp[1], 1);
380 dup2 (redirect ? inp[1] : errp[1], 2);
382 // Use close and not myclose -- we're in the child, and we
383 // aren't worried about the possible race condition.
384 close (inp[0]);
385 close (inp[1]);
386 if (! redirect)
388 close (errp[0]);
389 close (errp[1]);
391 close (outp[0]);
392 close (outp[1]);
393 close (msgp[0]);
395 // Change directory.
396 if (path != NULL)
398 if (chdir (path) != 0)
400 char c = errno;
401 write (msgp[1], &c, 1);
402 _exit (127);
405 // Make sure all file descriptors are closed. In
406 // multi-threaded programs, there is a race between when a
407 // descriptor is obtained, when we can set FD_CLOEXEC, and
408 // fork(). If the fork occurs before FD_CLOEXEC is set, the
409 // descriptor would leak to the execed process if we did not
410 // manually close it. So that is what we do. Since we
411 // close all the descriptors, it is redundant to set
412 // FD_CLOEXEC on them elsewhere.
413 int max_fd;
414 #ifdef HAVE_GETRLIMIT
415 rlimit rl;
416 int rv = getrlimit(RLIMIT_NOFILE, &rl);
417 if (rv == 0)
418 max_fd = rl.rlim_max - 1;
419 else
420 max_fd = 1024 - 1;
421 #else
422 max_fd = 1024 - 1;
423 #endif
424 while(max_fd > 2)
426 if (max_fd != msgp[1])
427 close (max_fd);
428 max_fd--;
430 // Make sure that SIGCHLD is unblocked for the new process.
431 sigset_t mask;
432 sigemptyset (&mask);
433 sigaddset (&mask, SIGCHLD);
434 sigprocmask (SIG_UNBLOCK, &mask, NULL);
436 execvp (args[0], args);
438 // Send the parent notification that the exec failed.
439 char c = errno;
440 write (msgp[1], &c, 1);
441 _exit (127);
444 // Parent. Close extra file descriptors and mark ours as
445 // close-on-exec.
446 pid = (jlong) pid_tmp;
448 myclose (outp[0]);
449 myclose (inp[1]);
450 if (! redirect)
451 myclose (errp[1]);
452 myclose (msgp[1]);
454 char c;
455 int r = read (msgp[0], &c, 1);
456 if (r == -1)
457 throw new IOException (JvNewStringUTF (strerror (errno)));
458 else if (r != 0)
459 throw new IOException (JvNewStringUTF (strerror (c)));
461 catch (java::lang::Throwable *thrown)
463 // Do some cleanup we only do on failure. If a stream object
464 // has been created, we must close the stream itself (to avoid
465 // duplicate closes when the stream object is collected).
466 // Otherwise we simply close the underlying file descriptor.
467 // We ignore errors here as they are uninteresting.
471 if (inputStream != NULL)
472 inputStream->close ();
473 else
474 myclose (inp[0]);
476 catch (java::lang::Throwable *ignore)
482 if (outputStream != NULL)
483 outputStream->close ();
484 else
485 myclose (outp[1]);
487 catch (java::lang::Throwable *ignore)
493 if (errorStream != NULL)
494 errorStream->close ();
495 else if (! redirect)
496 myclose (errp[0]);
498 catch (java::lang::Throwable *ignore)
502 // These are potentially duplicate, but it doesn't matter due to
503 // the use of myclose.
504 myclose (outp[0]);
505 myclose (inp[1]);
506 if (! redirect)
507 myclose (errp[1]);
508 myclose (msgp[1]);
510 exception = thrown;
513 myclose (msgp[0]);
514 cleanup (args, env, path);