OSDN Git Service

* auto-inc-dec.c: Fix pass description, remove apparent
[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_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>
33
34 #include <posix.h>
35 #include <posix-threads.h>
36 #include <jvm.h>
37
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>
53
54 using gnu::java::nio::channels::FileChannelImpl;
55 using namespace java::lang;
56
57 extern char **environ;
58
59 static char *
60 new_string (jstring string)
61 {
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;
67 }
68
69 static void
70 cleanup (char **args, char **env, char *path)
71 {
72   if (args != NULL)
73     {
74       for (int i = 0; args[i] != NULL; ++i)
75         _Jv_Free (args[i]);
76       _Jv_Free (args);
77     }
78   if (env != NULL)
79     {
80       for (int i = 0; env[i] != NULL; ++i)
81         _Jv_Free (env[i]);
82       _Jv_Free (env);
83     }
84   if (path != NULL)
85     _Jv_Free (path);
86 }
87
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)
93 {
94   if (fd != -1)
95     close (fd);
96   fd = -1;
97 }
98
99 namespace
100 {
101   struct ProcessManagerInternal
102   {
103     int pipe_ends[2];
104     struct sigaction old_sigaction;
105   };
106 }
107
108
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
118 {
119   if (PosixProcess$ProcessManager::nativeData != NULL)
120     {
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)
127         {
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);
134         }
135     }
136 }
137
138
139 // Get ready to enter the main reaper thread loop.
140 void
141 java::lang::PosixProcess$ProcessManager::init ()
142 {
143   // The nativeData is static to avoid races installing the signal
144   // handler in the case that it is chained.
145   if (nativeData == NULL )
146     {
147       ProcessManagerInternal *pmi =
148         (ProcessManagerInternal *)JvAllocBytes(sizeof(ProcessManagerInternal));
149
150       if (0 != ::pipe(pmi->pipe_ends))
151         goto error;
152
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);
157
158       nativeData = (::gnu::gcj::RawDataManaged *)pmi;
159
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));
164
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
174
175       if (-1 == sigaction (SIGCHLD, &sa, &pmi->old_sigaction))
176         goto error;
177     }
178   // All OK.
179   return;
180
181 error:
182   throw new InternalError (JvNewStringUTF (strerror (errno)));
183 }
184
185 void
186 java::lang::PosixProcess$ProcessManager::waitForSignal ()
187 {
188   // Wait for SIGCHLD
189   _Jv_UnBlockSigchld();
190   ProcessManagerInternal *pmi = (ProcessManagerInternal *)nativeData;
191
192   // Try to read multiple (64) notifications in one go.
193   char c[64];
194  ::read(pmi->pipe_ends[0], c, sizeof (c));
195
196   _Jv_BlockSigchld();
197
198   return;
199 }
200
201 jboolean java::lang::PosixProcess$ProcessManager::reap (PosixProcess *p)
202 {
203   pid_t rv;
204
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)));
210
211   if (rv == 0)
212     return false;   // No children to wait for.
213
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;
220 }
221
222 void
223 java::lang::PosixProcess$ProcessManager::signalReaper ()
224 {
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.
229 }
230
231 void
232 java::lang::PosixProcess::nativeDestroy ()
233 {
234   int c = ::kill ((pid_t) pid, SIGKILL);
235   if (c == 0)
236     return;
237   // kill() failed.
238   throw new InternalError (JvNewStringUTF (strerror (errno)));
239 }
240
241 void
242 java::lang::PosixProcess::nativeSpawn ()
243 {
244   using namespace java::io;
245
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;
262
263   try
264     {
265       // Transform arrays to native form.
266       args = (char **) _Jv_Malloc ((progarray->length + 1) * sizeof (char *));
267
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;
272
273       for (int i = 0; i < progarray->length; ++i)
274         args[i] = new_string (elts[i]);
275       args[progarray->length] = NULL;
276
277       if (envp)
278         {
279           bool need_path = true;
280           bool need_ld_library_path = true;
281           int i;
282
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);
289
290           // Initialize so we can gracefully recover.
291           for (i = 0; i < envp->length + 3; ++i)
292             env[i] = NULL;
293
294           for (i = 0; i < envp->length; ++i)
295             {
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;
302             }
303
304           if (need_path)
305             {
306               char *path_val = getenv ("PATH");
307               if (path_val)
308                 {
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++;
314                 }
315             }
316           if (need_ld_library_path)
317             {
318               char *path_val = getenv ("LD_LIBRARY_PATH");
319               if (path_val)
320                 {
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++;
327                 }
328             }
329           env[i] = NULL;
330         }
331
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 ());
336
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)));
345
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));
362
363       // We don't use vfork() because that would cause the local
364       // environment to be set by the child.
365
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)));
370
371     if (pid_tmp == 0)
372         {
373           // Child process, so remap descriptors, chdir and exec.
374           if (envp)
375             environ = env;
376
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);
381
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)
387             {
388               close (errp[0]);
389               close (errp[1]);
390             }
391           close (outp[0]);
392           close (outp[1]);
393           close (msgp[0]);
394
395           // Change directory.
396           if (path != NULL)
397             {
398               if (chdir (path) != 0)
399                 {
400                   char c = errno;
401                   write (msgp[1], &c, 1);
402                   _exit (127);
403                 }
404             }
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)
425             {
426               if (max_fd != msgp[1])
427                 close (max_fd);
428               max_fd--;
429             }
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);
435
436           execvp (args[0], args);
437
438           // Send the parent notification that the exec failed.
439           char c = errno;
440           write (msgp[1], &c, 1);
441           _exit (127);
442         }
443
444       // Parent.  Close extra file descriptors and mark ours as
445       // close-on-exec.
446       pid = (jlong) pid_tmp;
447
448       myclose (outp[0]);
449       myclose (inp[1]);
450       if (! redirect)
451         myclose (errp[1]);
452       myclose (msgp[1]);
453
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)));
460     }
461   catch (java::lang::Throwable *thrown)
462     {
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.
468
469       try
470         {
471           if (inputStream != NULL)
472             inputStream->close ();
473           else
474             myclose (inp[0]);
475         }
476       catch (java::lang::Throwable *ignore)
477         {
478         }
479
480       try
481         {
482           if (outputStream != NULL)
483             outputStream->close ();
484           else
485             myclose (outp[1]);
486         }
487       catch (java::lang::Throwable *ignore)
488         {
489         }
490
491       try
492         {
493           if (errorStream != NULL)
494             errorStream->close ();
495           else if (! redirect)
496             myclose (errp[0]);
497         }
498       catch (java::lang::Throwable *ignore)
499         {
500         }
501
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]);
509
510       exception = thrown;
511     }
512
513   myclose (msgp[0]);
514   cleanup (args, env, path);
515 }