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
19 #include <sys/types.h>
21 #ifdef HAVE_SYS_TIME_H
24 #ifdef HAVE_SYS_RESOURCE_H
25 #include <sys/resource.h>
35 #include <posix-threads.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;
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);
70 cleanup (char **args, char **env, char *path)
74 for (int i = 0; args[i] != NULL; ++i)
80 for (int i = 0; env[i] != NULL; ++i)
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
101 struct ProcessManagerInternal
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.
114 sigchld_handler (int sig, siginfo_t *si, void *third)
116 sigchld_handler (int sig)
119 if (PosixProcess$ProcessManager::nativeData != NULL)
121 ProcessManagerInternal *pmi =
122 (ProcessManagerInternal *)PosixProcess$ProcessManager::nativeData;
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)
129 if ((pmi->old_sigaction.sa_flags & SA_SIGINFO) != 0)
130 pmi->old_sigaction.sa_sigaction(sig, si, third);
133 (*pmi->old_sigaction.sa_handler)(sig);
139 // Get ready to enter the main reaper thread loop.
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))
153 // Make writing non-blocking so that the signal handler will
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.
163 memset (&sa, 0, sizeof (sa));
166 sa.sa_sigaction = sigchld_handler;
167 // We only want signals when the things exit.
168 sa.sa_flags = SA_NOCLDSTOP | SA_SIGINFO;
170 sa.sa_handler = sigchld_handler;
171 // We only want signals when the things exit.
172 sa.sa_flags = SA_NOCLDSTOP;
175 if (-1 == sigaction (SIGCHLD, &sa, &pmi->old_sigaction))
182 throw new InternalError (JvNewStringUTF (strerror (errno)));
186 java::lang::PosixProcess$ProcessManager::waitForSignal ()
189 _Jv_UnBlockSigchld();
190 ProcessManagerInternal *pmi = (ProcessManagerInternal *)nativeData;
192 // Try to read multiple (64) notifications in one go.
194 ::read(pmi->pipe_ends[0], c, sizeof (c));
201 jboolean java::lang::PosixProcess$ProcessManager::reap (PosixProcess *p)
205 // Try to get the return code from the child process.
207 rv = ::waitpid ((pid_t)p->pid, &status, WNOHANG);
209 throw new InternalError (JvNewStringUTF (strerror (errno)));
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();
223 java::lang::PosixProcess$ProcessManager::signalReaper ()
225 ProcessManagerInternal *pmi = (ProcessManagerInternal *)nativeData;
227 ::write(pmi->pipe_ends[1], &c, 1);
228 // Ignore errors. If EPIPE the reaper has already exited.
232 java::lang::PosixProcess::nativeDestroy ()
234 int c = ::kill ((pid_t) pid, SIGKILL);
238 throw new InternalError (JvNewStringUTF (strerror (errno)));
242 java::lang::PosixProcess::nativeSpawn ()
244 using namespace java::io;
246 // Initialize all locals here to make cleanup simpler.
250 int inp[2], outp[2], errp[2], msgp[2];
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)
273 for (int i = 0; i < progarray->length; ++i)
274 args[i] = new_string (elts[i]);
275 args[progarray->length] = NULL;
279 bool need_path = true;
280 bool need_ld_library_path = true;
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
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)
294 for (i = 0; i < envp->length; ++i)
296 env[i] = new_string (elts[i]);
297 if (!strncmp (env[i], "PATH=", sizeof("PATH=")))
299 if (!strncmp (env[i], "LD_LIBRARY_PATH=",
300 sizeof("LD_LIBRARY_PATH=")))
301 need_ld_library_path = false;
306 char *path_val = getenv ("PATH");
309 env[i] = (char *) _Jv_Malloc (strlen (path_val) +
310 sizeof("PATH=") + 1);
311 strcpy (env[i], "PATH=");
312 strcat (env[i], path_val);
316 if (need_ld_library_path)
318 char *path_val = getenv ("LD_LIBRARY_PATH");
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);
332 // We allocate this here because we can't call malloc() after
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.
350 errorStream = PosixProcess$EOFInputStream::instance;
353 new FileInputStream (new
354 FileChannelImpl (errp[0],
355 FileChannelImpl::READ));
357 new FileInputStream (new
358 FileChannelImpl (inp[0], FileChannelImpl::READ));
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.
368 if ((pid_tmp = fork ()) == -1)
369 throw new IOException (JvNewStringUTF (strerror (errno)));
373 // Child process, so remap descriptors, chdir and exec.
377 // We ignore errors from dup2 because they should never occur.
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.
398 if (chdir (path) != 0)
401 write (msgp[1], &c, 1);
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.
414 #ifdef HAVE_GETRLIMIT
416 int rv = getrlimit(RLIMIT_NOFILE, &rl);
418 max_fd = rl.rlim_max - 1;
426 if (max_fd != msgp[1])
430 // Make sure that SIGCHLD is unblocked for the new process.
433 sigaddset (&mask, SIGCHLD);
434 sigprocmask (SIG_UNBLOCK, &mask, NULL);
436 execvp (args[0], args);
438 // Send the parent notification that the exec failed.
440 write (msgp[1], &c, 1);
444 // Parent. Close extra file descriptors and mark ours as
446 pid = (jlong) pid_tmp;
455 int r = read (msgp[0], &c, 1);
457 throw new IOException (JvNewStringUTF (strerror (errno)));
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 ();
476 catch (java::lang::Throwable *ignore)
482 if (outputStream != NULL)
483 outputStream->close ();
487 catch (java::lang::Throwable *ignore)
493 if (errorStream != NULL)
494 errorStream->close ();
498 catch (java::lang::Throwable *ignore)
502 // These are potentially duplicate, but it doesn't matter due to
503 // the use of myclose.
514 cleanup (args, env, path);