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
);