OSDN Git Service

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