1 // natPosixProcess.cc - Native side of POSIX process code.
3 /* Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004, 2005 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
18 #include <sys/types.h>
30 #include <java/lang/ConcreteProcess$ProcessManager.h>
31 #include <java/lang/ConcreteProcess.h>
32 #include <java/lang/IllegalThreadStateException.h>
33 #include <java/lang/InternalError.h>
34 #include <java/lang/InterruptedException.h>
35 #include <java/lang/NullPointerException.h>
36 #include <java/lang/Thread.h>
37 #include <java/io/File.h>
38 #include <java/io/FileDescriptor.h>
39 #include <gnu/java/nio/channels/FileChannelImpl.h>
40 #include <java/io/FileInputStream.h>
41 #include <java/io/FileOutputStream.h>
42 #include <java/io/IOException.h>
43 #include <java/lang/OutOfMemoryError.h>
45 using gnu::java::nio::channels::FileChannelImpl
;
47 extern char **environ
;
50 new_string (jstring string
)
52 jsize s
= _Jv_GetStringUTFLength (string
);
53 char *buf
= (char *) _Jv_Malloc (s
+ 1);
54 _Jv_GetStringUTFRegion (string
, 0, string
->length(), buf
);
60 cleanup (char **args
, char **env
, char *path
)
64 for (int i
= 0; args
[i
] != NULL
; ++i
)
70 for (int i
= 0; env
[i
] != NULL
; ++i
)
78 // This makes our error handling a bit simpler and it lets us avoid
79 // thread bugs where we close a possibly-reopened file descriptor for
89 // There has to be a signal handler in order to be able to
90 // sigwait() on SIGCHLD. The information passed is ignored as it
91 // will be recovered by the waitpid() call.
99 // Get ready to enter the main reaper thread loop.
101 java::lang::ConcreteProcess$
ProcessManager::init ()
103 using namespace java::lang
;
104 // Remenber our PID so other threads can kill us.
105 reaperPID
= (jlong
) pthread_self ();
107 // SIGCHLD is blocked in all threads in posix-threads.cc.
108 // Setup the SIGCHLD handler.
110 memset (&sa
, 0, sizeof (sa
));
112 sa
.sa_handler
= sigchld_handler
;
113 // We only want signals when the things exit.
114 sa
.sa_flags
= SA_NOCLDSTOP
;
116 if (-1 == sigaction (SIGCHLD
, &sa
, NULL
))
123 throw new InternalError (JvNewStringUTF (strerror (errno
)));
127 java::lang::ConcreteProcess$
ProcessManager::waitForSignal ()
131 pthread_sigmask (0, NULL
, &mask
);
132 sigdelset (&mask
, SIGCHLD
);
134 // Use sigsuspend() instead of sigwait() as sigwait() doesn't play
135 // nicely with the GC's use of signals.
138 // Do not check sigsuspend return value. The only legitimate return
139 // is EINTR, but there is a known kernel bug affecting alpha-linux
140 // wrt sigsuspend+handler+sigreturn that can result in a return value
141 // of __NR_sigsuspend and errno unset. Don't fail unnecessarily on
142 // older kernel versions.
148 jboolean
java::lang::ConcreteProcess$
ProcessManager::reap ()
150 using namespace java::lang
;
156 // Get the return code from a dead child process.
158 pid
= waitpid ((pid_t
) - 1, &status
, WNOHANG
);
168 return true; // No children to wait for.
170 // Look up the process in our pid map.
171 ConcreteProcess
* process
= removeProcessFromMap ((jlong
) pid
);
175 JvSynchronize
sync (process
);
176 process
->status
= WIFEXITED (status
) ? WEXITSTATUS (status
) : -1;
177 process
->state
= ConcreteProcess::STATE_TERMINATED
;
178 process
->processTerminationCleanup();
179 process
->notifyAll ();
183 // Unknown child. How did this happen?
184 fprintf (stderr
, "Reaped unknown child pid = %ld\n", (long) pid
);
189 throw new InternalError (JvNewStringUTF (strerror (errno
)));
193 java::lang::ConcreteProcess$
ProcessManager::signalReaper ()
195 int c
= pthread_kill ((pthread_t
) reaperPID
, SIGCHLD
);
198 // pthread_kill() failed.
199 throw new InternalError (JvNewStringUTF (strerror (c
)));
203 java::lang::ConcreteProcess::nativeDestroy ()
205 int c
= kill ((pid_t
) pid
, SIGKILL
);
209 throw new InternalError (JvNewStringUTF (strerror (errno
)));
213 java::lang::ConcreteProcess::nativeSpawn ()
215 using namespace java::io
;
217 // Initialize all locals here to make cleanup simpler.
221 int inp
[2], outp
[2], errp
[2], msgp
[2];
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
)
244 for (int i
= 0; i
< progarray
->length
; ++i
)
245 args
[i
] = new_string (elts
[i
]);
246 args
[progarray
->length
] = NULL
;
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
)
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
265 path
= new_string (dir
->getPath ());
267 // Create pipes for I/O. MSGP is for communicating exec()
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.
277 new FileInputStream (new
278 FileChannelImpl (errp
[0], FileChannelImpl::READ
));
280 new FileInputStream (new
281 FileChannelImpl (inp
[0], FileChannelImpl::READ
));
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.
291 if ((pid_tmp
= fork ()) == -1)
292 throw new IOException (JvNewStringUTF (strerror (errno
)));
296 // Child process, so remap descriptors, chdir and exec.
299 // Preserve PATH and LD_LIBRARY_PATH unless specified
301 char *path_val
= getenv ("PATH");
302 char *ld_path_val
= getenv ("LD_LIBRARY_PATH");
304 if (path_val
&& getenv ("PATH") == NULL
)
307 (char *) _Jv_Malloc (strlen (path_val
) + 5 + 1);
308 strcpy (path_env
, "PATH=");
309 strcat (path_env
, path_val
);
312 if (ld_path_val
&& getenv ("LD_LIBRARY_PATH") == NULL
)
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.
327 // Use close and not myclose -- we're in the child, and we
328 // aren't worried about the possible race condition.
340 if (chdir (path
) != 0)
343 write (msgp
[1], &c
, 1);
348 // Make sure that SIGCHLD is unblocked for the new process.
351 sigaddset (&mask
, SIGCHLD
);
352 sigprocmask (SIG_UNBLOCK
, &mask
, NULL
);
354 execvp (args
[0], args
);
356 // Send the parent notification that the exec failed.
358 write (msgp
[1], &c
, 1);
362 // Parent. Close extra file descriptors and mark ours as
364 pid
= (jlong
) pid_tmp
;
372 int r
= read (msgp
[0], &c
, 1);
374 throw new IOException (JvNewStringUTF (strerror (errno
)));
376 throw new IOException (JvNewStringUTF (strerror (c
)));
378 catch (java::lang::Throwable
*thrown
)
380 // Do some cleanup we only do on failure. If a stream object
381 // has been created, we must close the stream itself (to avoid
382 // duplicate closes when the stream object is collected).
383 // Otherwise we simply close the underlying file descriptor.
384 // We ignore errors here as they are uninteresting.
388 if (inputStream
!= NULL
)
389 inputStream
->close ();
393 catch (java::lang::Throwable
*ignore
)
399 if (outputStream
!= NULL
)
400 outputStream
->close ();
404 catch (java::lang::Throwable
*ignore
)
410 if (errorStream
!= NULL
)
411 errorStream
->close ();
415 catch (java::lang::Throwable
*ignore
)
419 // These are potentially duplicate, but it doesn't matter due to
420 // the use of myclose.
430 cleanup (args
, env
, path
);
432 if (exception
== NULL
)
434 fcntl (outp
[1], F_SETFD
, FD_CLOEXEC
);
435 fcntl (inp
[0], F_SETFD
, FD_CLOEXEC
);
436 fcntl (errp
[0], F_SETFD
, FD_CLOEXEC
);