a6c049b54b1506e2f0eb32fb0475205d9f2c9a80
1 // natPosixProcess.cc - Native side of POSIX process code.
3 /* Copyright (C) 1998, 1999, 2000, 2002 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>
28 #include <java/lang/ConcreteProcess.h>
29 #include <java/lang/IllegalThreadStateException.h>
30 #include <java/lang/InterruptedException.h>
31 #include <java/lang/NullPointerException.h>
32 #include <java/lang/Thread.h>
33 #include <java/io/File.h>
34 #include <java/io/FileDescriptor.h>
35 #include <java/io/FileInputStream.h>
36 #include <java/io/FileOutputStream.h>
37 #include <java/io/IOException.h>
38 #include <java/lang/OutOfMemoryError.h>
40 extern char **environ
;
43 java::lang::ConcreteProcess::destroy (void)
48 kill ((pid_t
) pid
, SIGKILL
);
53 java::lang::ConcreteProcess::waitFor (void)
58 int r
= waitpid ((pid_t
) pid
, &wstat
, 0);
62 if (java::lang::Thread::interrupted())
63 throw new InterruptedException (JvNewStringLatin1 (strerror
70 if (WIFEXITED (wstat
))
71 status
= WEXITSTATUS (wstat
);
81 new_string (jstring string
)
83 jsize s
= _Jv_GetStringUTFLength (string
);
84 char *buf
= (char *) _Jv_Malloc (s
+ 1);
85 _Jv_GetStringUTFRegion (string
, 0, s
, buf
);
91 cleanup (char **args
, char **env
)
95 for (int i
= 0; args
[i
] != NULL
; ++i
)
101 for (int i
= 0; env
[i
] != NULL
; ++i
)
107 // This makes our error handling a bit simpler and it lets us avoid
108 // thread bugs where we close a possibly-reopened file descriptor for
119 java::lang::ConcreteProcess::startProcess (jstringArray progarray
,
123 using namespace java::io
;
127 // Initialize all locals here to make cleanup simpler.
130 int inp
[2], outp
[2], errp
[2], msgp
[2];
139 java::lang::Throwable
*exc
= NULL
;
146 // Transform arrays to native form.
147 args
= (char **) _Jv_Malloc ((progarray
->length
+ 1)
150 // Initialize so we can gracefully recover.
151 jstring
*elts
= elements (progarray
);
152 for (int i
= 0; i
<= progarray
->length
; ++i
)
155 for (int i
= 0; i
< progarray
->length
; ++i
)
156 args
[i
] = new_string (elts
[i
]);
157 args
[progarray
->length
] = NULL
;
161 env
= (char **) _Jv_Malloc ((envp
->length
+ 1) * sizeof (char *));
162 elts
= elements (envp
);
164 // Initialize so we can gracefully recover.
165 for (int i
= 0; i
<= envp
->length
; ++i
)
168 for (int i
= 0; i
< envp
->length
; ++i
)
169 env
[i
] = new_string (elts
[i
]);
170 env
[envp
->length
] = NULL
;
173 // Create pipes for I/O. MSGP is for communicating exec()
175 if (pipe (inp
) || pipe (outp
) || pipe (errp
) || pipe (msgp
)
176 || fcntl (msgp
[1], F_SETFD
, FD_CLOEXEC
))
177 throw new IOException (JvNewStringLatin1 (strerror (errno
)));
179 // We create the streams before forking. Otherwise if we had an
180 // error while creating the streams we would have run the child
181 // with no way to communicate with it.
182 errorStream
= new FileInputStream (new FileDescriptor (errp
[0]));
183 inputStream
= new FileInputStream (new FileDescriptor (inp
[0]));
184 outputStream
= new FileOutputStream (new FileDescriptor (outp
[1]));
186 // We don't use vfork() because that would cause the local
187 // environment to be set by the child.
188 if ((pid
= (jlong
) fork ()) == -1)
189 throw new IOException (JvNewStringLatin1 (strerror (errno
)));
193 // Child process, so remap descriptors, chdir and exec.
197 // Preserve PATH and LD_LIBRARY_PATH unless specified
199 char *path_val
= getenv ("PATH");
200 char *ld_path_val
= getenv ("LD_LIBRARY_PATH");
202 if (getenv ("PATH") == NULL
)
204 char *path_env
= (char *) _Jv_Malloc (strlen (path_val
)
206 strcpy (path_env
, "PATH=");
207 strcat (path_env
, path_val
);
210 if (getenv ("LD_LIBRARY_PATH") == NULL
)
213 = (char *) _Jv_Malloc (strlen (ld_path_val
) + 16 + 1);
214 strcpy (ld_path_env
, "LD_LIBRARY_PATH=");
215 strcat (ld_path_env
, ld_path_val
);
216 putenv (ld_path_env
);
220 // We ignore errors from dup2 because they should never occur.
225 // Use close and not myclose -- we're in the child, and we
226 // aren't worried about the possible race condition.
238 // We don't care about leaking memory here; this process
239 // is about to terminate one way or another.
240 if (chdir (new_string (dir
->getPath ())) != 0)
243 write (msgp
[1], &c
, 1);
248 execvp (args
[0], args
);
250 // Send the parent notification that the exec failed.
252 write (msgp
[1], &c
, 1);
256 // Parent. Close extra file descriptors and mark ours as
264 int r
= read (msgp
[0], &c
, 1);
266 throw new IOException (JvNewStringLatin1 (strerror (errno
)));
268 throw new IOException (JvNewStringLatin1 (strerror (c
)));
270 catch (java::lang::Throwable
*thrown
)
272 // Do some cleanup we only do on failure. If a stream object
273 // has been created, we must close the stream itself (to avoid
274 // duplicate closes when the stream object is collected).
275 // Otherwise we simply close the underlying file descriptor.
276 // We ignore errors here as they are uninteresting.
280 if (inputStream
!= NULL
)
281 inputStream
->close ();
285 catch (java::lang::Throwable
*ignore
)
291 if (outputStream
!= NULL
)
292 outputStream
->close ();
296 catch (java::lang::Throwable
*ignore
)
302 if (errorStream
!= NULL
)
303 errorStream
->close ();
307 catch (java::lang::Throwable
*ignore
)
311 // These are potentially duplicate, but it doesn't matter due to
312 // the use of myclose.
328 fcntl (outp
[1], F_SETFD
, FD_CLOEXEC
);
329 fcntl (inp
[0], F_SETFD
, FD_CLOEXEC
);
330 fcntl (errp
[0], F_SETFD
, FD_CLOEXEC
);