Mark as release
[official-gcc.git] / libjava / java / lang / natPosixProcess.cc
blob77ac6925354fe835cc89dfbdf64a5e3cfc68bfc6
1 // natPosixProcess.cc - Native side of POSIX process code.
3 /* Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004, 2005, 2006 Free Software Foundation
5 This file is part of libgcj.
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
9 details. */
11 #include <config.h>
13 #ifdef HAVE_UNISTD_H
14 #include <unistd.h>
15 #endif
16 #include <errno.h>
17 #include <fcntl.h>
18 #include <sys/types.h>
19 #include <sys/wait.h>
20 #ifdef HAVE_SYS_RESOURCE_H
21 #include <sys/resource.h>
22 #endif
23 #include <signal.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <unistd.h>
28 #include <pthread.h>
30 #include <gcj/cni.h>
31 #include <jvm.h>
33 #include <java/lang/ConcreteProcess$ProcessManager.h>
34 #include <java/lang/ConcreteProcess.h>
35 #include <java/lang/IllegalThreadStateException.h>
36 #include <java/lang/InternalError.h>
37 #include <java/lang/InterruptedException.h>
38 #include <java/lang/NullPointerException.h>
39 #include <java/lang/Thread.h>
40 #include <java/io/File.h>
41 #include <java/io/FileDescriptor.h>
42 #include <gnu/java/nio/channels/FileChannelImpl.h>
43 #include <java/io/FileInputStream.h>
44 #include <java/io/FileOutputStream.h>
45 #include <java/io/IOException.h>
46 #include <java/lang/OutOfMemoryError.h>
48 using gnu::java::nio::channels::FileChannelImpl;
50 extern char **environ;
52 static char *
53 new_string (jstring string)
55 jsize s = _Jv_GetStringUTFLength (string);
56 char *buf = (char *) _Jv_Malloc (s + 1);
57 _Jv_GetStringUTFRegion (string, 0, string->length(), buf);
58 buf[s] = '\0';
59 return buf;
62 static void
63 cleanup (char **args, char **env, char *path)
65 if (args != NULL)
67 for (int i = 0; args[i] != NULL; ++i)
68 _Jv_Free (args[i]);
69 _Jv_Free (args);
71 if (env != NULL)
73 for (int i = 0; env[i] != NULL; ++i)
74 _Jv_Free (env[i]);
75 _Jv_Free (env);
77 if (path != NULL)
78 _Jv_Free (path);
81 // This makes our error handling a bit simpler and it lets us avoid
82 // thread bugs where we close a possibly-reopened file descriptor for
83 // a second time.
84 static void
85 myclose (int &fd)
87 if (fd != -1)
88 close (fd);
89 fd = -1;
92 // There has to be a signal handler in order to be able to
93 // sigwait() on SIGCHLD. The information passed is ignored as it
94 // will be recovered by the waitpid() call.
95 static void
96 sigchld_handler (int)
98 // Ignore.
102 // Get ready to enter the main reaper thread loop.
103 void
104 java::lang::ConcreteProcess$ProcessManager::init ()
106 using namespace java::lang;
107 // Remenber our PID so other threads can kill us.
108 reaperPID = (jlong) pthread_self ();
110 // SIGCHLD is blocked in all threads in posix-threads.cc.
111 // Setup the SIGCHLD handler.
112 struct sigaction sa;
113 memset (&sa, 0, sizeof (sa));
115 sa.sa_handler = sigchld_handler;
116 // We only want signals when the things exit.
117 sa.sa_flags = SA_NOCLDSTOP;
119 if (-1 == sigaction (SIGCHLD, &sa, NULL))
120 goto error;
122 // All OK.
123 return;
125 error:
126 throw new InternalError (JvNewStringUTF (strerror (errno)));
129 void
130 java::lang::ConcreteProcess$ProcessManager::waitForSignal ()
132 // Wait for SIGCHLD
133 sigset_t mask;
134 pthread_sigmask (0, NULL, &mask);
135 sigdelset (&mask, SIGCHLD);
137 // Use sigsuspend() instead of sigwait() as sigwait() doesn't play
138 // nicely with the GC's use of signals.
139 sigsuspend (&mask);
141 // Do not check sigsuspend return value. The only legitimate return
142 // is EINTR, but there is a known kernel bug affecting alpha-linux
143 // wrt sigsuspend+handler+sigreturn that can result in a return value
144 // of __NR_sigsuspend and errno unset. Don't fail unnecessarily on
145 // older kernel versions.
147 // All OK.
148 return;
151 jboolean java::lang::ConcreteProcess$ProcessManager::reap ()
153 using namespace java::lang;
155 pid_t pid;
157 for (;;)
159 // Get the return code from a dead child process.
160 int status;
161 pid = waitpid ((pid_t) - 1, &status, WNOHANG);
162 if (pid == -1)
164 if (errno == ECHILD)
165 return false;
166 else
167 goto error;
170 if (pid == 0)
171 return true; // No children to wait for.
173 // Look up the process in our pid map.
174 ConcreteProcess * process = removeProcessFromMap ((jlong) pid);
176 // Note that if process==NULL, then we have an unknown child.
177 // This is not common, but can happen, and isn't an error.
178 if (process)
180 JvSynchronize sync (process);
181 process->status = WIFEXITED (status) ? WEXITSTATUS (status) : -1;
182 process->state = ConcreteProcess::STATE_TERMINATED;
183 process->processTerminationCleanup();
184 process->notifyAll ();
188 error:
189 throw new InternalError (JvNewStringUTF (strerror (errno)));
192 void
193 java::lang::ConcreteProcess$ProcessManager::signalReaper ()
195 int c = pthread_kill ((pthread_t) reaperPID, SIGCHLD);
196 if (c == 0)
197 return;
198 // pthread_kill() failed.
199 throw new InternalError (JvNewStringUTF (strerror (c)));
202 void
203 java::lang::ConcreteProcess::nativeDestroy ()
205 int c = kill ((pid_t) pid, SIGKILL);
206 if (c == 0)
207 return;
208 // kill() failed.
209 throw new InternalError (JvNewStringUTF (strerror (errno)));
212 void
213 java::lang::ConcreteProcess::nativeSpawn ()
215 using namespace java::io;
217 // Initialize all locals here to make cleanup simpler.
218 char **args = NULL;
219 char **env = NULL;
220 char *path = NULL;
221 int inp[2], outp[2], errp[2], msgp[2];
222 inp[0] = -1;
223 inp[1] = -1;
224 outp[0] = -1;
225 outp[1] = -1;
226 errp[0] = -1;
227 errp[1] = -1;
228 msgp[0] = -1;
229 msgp[1] = -1;
230 errorStream = NULL;
231 inputStream = NULL;
232 outputStream = NULL;
236 // Transform arrays to native form.
237 args = (char **) _Jv_Malloc ((progarray->length + 1) * sizeof (char *));
239 // Initialize so we can gracefully recover.
240 jstring *elts = elements (progarray);
241 for (int i = 0; i <= progarray->length; ++i)
242 args[i] = NULL;
244 for (int i = 0; i < progarray->length; ++i)
245 args[i] = new_string (elts[i]);
246 args[progarray->length] = NULL;
248 if (envp)
250 env = (char **) _Jv_Malloc ((envp->length + 1) * sizeof (char *));
251 elts = elements (envp);
253 // Initialize so we can gracefully recover.
254 for (int i = 0; i <= envp->length; ++i)
255 env[i] = NULL;
257 for (int i = 0; i < envp->length; ++i)
258 env[i] = new_string (elts[i]);
259 env[envp->length] = NULL;
262 // We allocate this here because we can't call malloc() after
263 // the fork.
264 if (dir != NULL)
265 path = new_string (dir->getPath ());
267 // Create pipes for I/O. MSGP is for communicating exec()
268 // status.
269 if (pipe (inp) || pipe (outp) || pipe (errp) || pipe (msgp)
270 || fcntl (msgp[1], F_SETFD, FD_CLOEXEC))
271 throw new IOException (JvNewStringUTF (strerror (errno)));
273 // We create the streams before forking. Otherwise if we had an
274 // error while creating the streams we would have run the child
275 // with no way to communicate with it.
276 errorStream =
277 new FileInputStream (new
278 FileChannelImpl (errp[0], FileChannelImpl::READ));
279 inputStream =
280 new FileInputStream (new
281 FileChannelImpl (inp[0], FileChannelImpl::READ));
282 outputStream =
283 new FileOutputStream (new FileChannelImpl (outp[1],
284 FileChannelImpl::WRITE));
286 // We don't use vfork() because that would cause the local
287 // environment to be set by the child.
289 // Use temporary for fork result to avoid dirtying an extra page.
290 pid_t pid_tmp;
291 if ((pid_tmp = fork ()) == -1)
292 throw new IOException (JvNewStringUTF (strerror (errno)));
294 if (pid_tmp == 0)
296 // Child process, so remap descriptors, chdir and exec.
297 if (envp)
299 // Preserve PATH and LD_LIBRARY_PATH unless specified
300 // explicitly.
301 char *path_val = getenv ("PATH");
302 char *ld_path_val = getenv ("LD_LIBRARY_PATH");
303 environ = env;
304 if (path_val && getenv ("PATH") == NULL)
306 char *path_env =
307 (char *) _Jv_Malloc (strlen (path_val) + 5 + 1);
308 strcpy (path_env, "PATH=");
309 strcat (path_env, path_val);
310 putenv (path_env);
312 if (ld_path_val && getenv ("LD_LIBRARY_PATH") == NULL)
314 char *ld_path_env =
315 (char *) _Jv_Malloc (strlen (ld_path_val) + 16 + 1);
316 strcpy (ld_path_env, "LD_LIBRARY_PATH=");
317 strcat (ld_path_env, ld_path_val);
318 putenv (ld_path_env);
322 // We ignore errors from dup2 because they should never occur.
323 dup2 (outp[0], 0);
324 dup2 (inp[1], 1);
325 dup2 (errp[1], 2);
327 // Use close and not myclose -- we're in the child, and we
328 // aren't worried about the possible race condition.
329 close (inp[0]);
330 close (inp[1]);
331 close (errp[0]);
332 close (errp[1]);
333 close (outp[0]);
334 close (outp[1]);
335 close (msgp[0]);
337 // Change directory.
338 if (path != NULL)
340 if (chdir (path) != 0)
342 char c = errno;
343 write (msgp[1], &c, 1);
344 _exit (127);
347 // Make sure all file descriptors are closed. In
348 // multi-threaded programs, there is a race between when a
349 // descriptor is obtained, when we can set FD_CLOEXEC, and
350 // fork(). If the fork occurs before FD_CLOEXEC is set, the
351 // descriptor would leak to the execed process if we did not
352 // manually close it. So that is what we do. Since we
353 // close all the descriptors, it is redundant to set
354 // FD_CLOEXEC on them elsewhere.
355 int max_fd;
356 #ifdef HAVE_GETRLIMIT
357 rlimit rl;
358 int rv = getrlimit(RLIMIT_NOFILE, &rl);
359 if (rv == 0)
360 max_fd = rl.rlim_max - 1;
361 else
362 max_fd = 1024 - 1;
363 #else
364 max_fd = 1024 - 1;
365 #endif
366 while(max_fd > 2)
368 if (max_fd != msgp[1])
369 close (max_fd);
370 max_fd--;
372 // Make sure that SIGCHLD is unblocked for the new process.
373 sigset_t mask;
374 sigemptyset (&mask);
375 sigaddset (&mask, SIGCHLD);
376 sigprocmask (SIG_UNBLOCK, &mask, NULL);
378 execvp (args[0], args);
380 // Send the parent notification that the exec failed.
381 char c = errno;
382 write (msgp[1], &c, 1);
383 _exit (127);
386 // Parent. Close extra file descriptors and mark ours as
387 // close-on-exec.
388 pid = (jlong) pid_tmp;
390 myclose (outp[0]);
391 myclose (inp[1]);
392 myclose (errp[1]);
393 myclose (msgp[1]);
395 char c;
396 int r = read (msgp[0], &c, 1);
397 if (r == -1)
398 throw new IOException (JvNewStringUTF (strerror (errno)));
399 else if (r != 0)
400 throw new IOException (JvNewStringUTF (strerror (c)));
402 catch (java::lang::Throwable *thrown)
404 // Do some cleanup we only do on failure. If a stream object
405 // has been created, we must close the stream itself (to avoid
406 // duplicate closes when the stream object is collected).
407 // Otherwise we simply close the underlying file descriptor.
408 // We ignore errors here as they are uninteresting.
412 if (inputStream != NULL)
413 inputStream->close ();
414 else
415 myclose (inp[0]);
417 catch (java::lang::Throwable *ignore)
423 if (outputStream != NULL)
424 outputStream->close ();
425 else
426 myclose (outp[1]);
428 catch (java::lang::Throwable *ignore)
434 if (errorStream != NULL)
435 errorStream->close ();
436 else
437 myclose (errp[0]);
439 catch (java::lang::Throwable *ignore)
443 // These are potentially duplicate, but it doesn't matter due to
444 // the use of myclose.
445 myclose (outp[0]);
446 myclose (inp[1]);
447 myclose (errp[1]);
448 myclose (msgp[1]);
450 exception = thrown;
453 myclose (msgp[0]);
454 cleanup (args, env, path);