1 // natPosixProcess.cc - Native side of POSIX process code.
3 /* Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004 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 ()
129 using namespace java::lang
;
134 sigaddset (&mask
, SIGCHLD
);
137 int c
= sigwait (&mask
, &sig
);
146 throw new InternalError (JvNewStringUTF (strerror (c
)));
149 jboolean
java::lang::ConcreteProcess$
ProcessManager::reap ()
151 using namespace java::lang
;
157 // Get the return code from a dead child process.
159 pid
= waitpid ((pid_t
) - 1, &status
, WNOHANG
);
169 return true; // No children to wait for.
171 // Look up the process in our pid map.
172 ConcreteProcess
* process
= removeProcessFromMap ((jlong
) pid
);
176 JvSynchronize
sync (process
);
177 process
->status
= WIFEXITED (status
) ? WEXITSTATUS (status
) : -1;
178 process
->state
= ConcreteProcess::STATE_TERMINATED
;
179 process
->processTerminationCleanup();
180 process
->notifyAll ();
184 // Unknown child. How did this happen?
185 fprintf (stderr
, "Reaped unknown child pid = %ld\n", (long) pid
);
190 throw new InternalError (JvNewStringUTF (strerror (errno
)));
194 java::lang::ConcreteProcess$
ProcessManager::signalReaper ()
196 int c
= pthread_kill ((pthread_t
) reaperPID
, SIGCHLD
);
199 // pthread_kill() failed.
200 throw new InternalError (JvNewStringUTF (strerror (c
)));
204 java::lang::ConcreteProcess::nativeDestroy ()
206 int c
= kill ((pid_t
) pid
, SIGKILL
);
210 throw new InternalError (JvNewStringUTF (strerror (errno
)));
214 java::lang::ConcreteProcess::nativeSpawn ()
216 using namespace java::io
;
218 // Initialize all locals here to make cleanup simpler.
222 int inp
[2], outp
[2], errp
[2], msgp
[2];
237 // Transform arrays to native form.
238 args
= (char **) _Jv_Malloc ((progarray
->length
+ 1) * sizeof (char *));
240 // Initialize so we can gracefully recover.
241 jstring
*elts
= elements (progarray
);
242 for (int i
= 0; i
<= progarray
->length
; ++i
)
245 for (int i
= 0; i
< progarray
->length
; ++i
)
246 args
[i
] = new_string (elts
[i
]);
247 args
[progarray
->length
] = NULL
;
251 env
= (char **) _Jv_Malloc ((envp
->length
+ 1) * sizeof (char *));
252 elts
= elements (envp
);
254 // Initialize so we can gracefully recover.
255 for (int i
= 0; i
<= envp
->length
; ++i
)
258 for (int i
= 0; i
< envp
->length
; ++i
)
259 env
[i
] = new_string (elts
[i
]);
260 env
[envp
->length
] = NULL
;
263 // We allocate this here because we can't call malloc() after
266 path
= new_string (dir
->getPath ());
268 // Create pipes for I/O. MSGP is for communicating exec()
270 if (pipe (inp
) || pipe (outp
) || pipe (errp
) || pipe (msgp
)
271 || fcntl (msgp
[1], F_SETFD
, FD_CLOEXEC
))
272 throw new IOException (JvNewStringUTF (strerror (errno
)));
274 // We create the streams before forking. Otherwise if we had an
275 // error while creating the streams we would have run the child
276 // with no way to communicate with it.
278 new FileInputStream (new
279 FileChannelImpl (errp
[0], FileChannelImpl::READ
));
281 new FileInputStream (new
282 FileChannelImpl (inp
[0], FileChannelImpl::READ
));
284 new FileOutputStream (new FileChannelImpl (outp
[1],
285 FileChannelImpl::WRITE
));
287 // We don't use vfork() because that would cause the local
288 // environment to be set by the child.
290 // Use temporary for fork result to avoid dirtying an extra page.
292 if ((pid_tmp
= fork ()) == -1)
293 throw new IOException (JvNewStringUTF (strerror (errno
)));
297 // Child process, so remap descriptors, chdir and exec.
300 // Preserve PATH and LD_LIBRARY_PATH unless specified
302 char *path_val
= getenv ("PATH");
303 char *ld_path_val
= getenv ("LD_LIBRARY_PATH");
305 if (path_val
&& getenv ("PATH") == NULL
)
308 (char *) _Jv_Malloc (strlen (path_val
) + 5 + 1);
309 strcpy (path_env
, "PATH=");
310 strcat (path_env
, path_val
);
313 if (ld_path_val
&& getenv ("LD_LIBRARY_PATH") == NULL
)
316 (char *) _Jv_Malloc (strlen (ld_path_val
) + 16 + 1);
317 strcpy (ld_path_env
, "LD_LIBRARY_PATH=");
318 strcat (ld_path_env
, ld_path_val
);
319 putenv (ld_path_env
);
323 // We ignore errors from dup2 because they should never occur.
328 // Use close and not myclose -- we're in the child, and we
329 // aren't worried about the possible race condition.
341 if (chdir (path
) != 0)
344 write (msgp
[1], &c
, 1);
349 execvp (args
[0], args
);
351 // Send the parent notification that the exec failed.
353 write (msgp
[1], &c
, 1);
357 // Parent. Close extra file descriptors and mark ours as
359 pid
= (jlong
) pid_tmp
;
367 int r
= read (msgp
[0], &c
, 1);
369 throw new IOException (JvNewStringUTF (strerror (errno
)));
371 throw new IOException (JvNewStringUTF (strerror (c
)));
373 catch (java::lang::Throwable
*thrown
)
375 // Do some cleanup we only do on failure. If a stream object
376 // has been created, we must close the stream itself (to avoid
377 // duplicate closes when the stream object is collected).
378 // Otherwise we simply close the underlying file descriptor.
379 // We ignore errors here as they are uninteresting.
383 if (inputStream
!= NULL
)
384 inputStream
->close ();
388 catch (java::lang::Throwable
*ignore
)
394 if (outputStream
!= NULL
)
395 outputStream
->close ();
399 catch (java::lang::Throwable
*ignore
)
405 if (errorStream
!= NULL
)
406 errorStream
->close ();
410 catch (java::lang::Throwable
*ignore
)
414 // These are potentially duplicate, but it doesn't matter due to
415 // the use of myclose.
425 cleanup (args
, env
, path
);
427 if (exception
== NULL
)
429 fcntl (outp
[1], F_SETFD
, FD_CLOEXEC
);
430 fcntl (inp
[0], F_SETFD
, FD_CLOEXEC
);
431 fcntl (errp
[0], F_SETFD
, FD_CLOEXEC
);