From: Tom Tromey Date: Wed, 6 Mar 2002 05:13:58 +0000 (+0000) Subject: natPosixProcess.cc (fail): Removed. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=355526af2b3527bde465ccbfbb6a6af42a74ceea;p=gcc.git natPosixProcess.cc (fail): Removed. * java/lang/natPosixProcess.cc (fail): Removed. (startProcess): Simplified error-handling. Preserve LD_LIBRARY_PATH across exec. From-SVN: r50342 --- diff --git a/libjava/ChangeLog b/libjava/ChangeLog index 7d37bc42928..392d370d115 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -1,5 +1,9 @@ 2002-03-05 Tom Tromey + * java/lang/natPosixProcess.cc (fail): Removed. + (startProcess): Simplified error-handling. Preserve + LD_LIBRARY_PATH across exec. + * jni.cc (_Jv_LookupJNIMethod): Throw UnsatisfiedLinkError, not AbstractMethodError. diff --git a/libjava/java/lang/natPosixProcess.cc b/libjava/java/lang/natPosixProcess.cc index 5ff49e3e382..b480afb81a8 100644 --- a/libjava/java/lang/natPosixProcess.cc +++ b/libjava/java/lang/natPosixProcess.cc @@ -114,38 +114,6 @@ myclose (int &fd) fd = -1; } -static void -fail (int error_value, char **args, char **env, - int *one = NULL, int *two = NULL, - int *three = NULL, int *four = NULL, - java::lang::Throwable *t = NULL) -{ - cleanup (args, env); - if (one != NULL) - { - myclose (one[0]); - myclose (one[1]); - } - if (two != NULL) - { - myclose (two[0]); - myclose (two[1]); - } - if (three != NULL) - { - myclose (three[0]); - myclose (three[1]); - } - if (four != NULL) - { - myclose (four[0]); - myclose (four[1]); - } - if (t == NULL) - t = new java::io::IOException (JvNewStringLatin1 (strerror (error_value))); - throw t; -} - void java::lang::ConcreteProcess::startProcess (jstringArray progarray, jstringArray envp) @@ -154,21 +122,34 @@ java::lang::ConcreteProcess::startProcess (jstringArray progarray, hasExited = false; - if (! progarray) - throw new NullPointerException; - - // Transform arrays to native form. - char **args = (char **) _Jv_Malloc ((progarray->length + 1) - * sizeof (char *)); + // Initialize all locals here to make cleanup simpler. + char **args = NULL; char **env = NULL; - - // Initialize so we can gracefully recover. - jstring *elts = elements (progarray); - for (int i = 0; i <= progarray->length; ++i) - args[i] = NULL; + int inp[2], outp[2], errp[2], msgp[2]; + inp[0] = -1; + inp[1] = -1; + outp[0] = -1; + outp[1] = -1; + errp[0] = -1; + errp[1] = -1; + msgp[0] = -1; + msgp[1] = -1; + java::lang::Throwable *exc = NULL; + errorStream = NULL; + inputStream = NULL; + outputStream = NULL; try { + // Transform arrays to native form. + args = (char **) _Jv_Malloc ((progarray->length + 1) + * sizeof (char *)); + + // Initialize so we can gracefully recover. + jstring *elts = elements (progarray); + for (int i = 0; i <= progarray->length; ++i) + args[i] = NULL; + for (int i = 0; i < progarray->length; ++i) args[i] = new_string (elts[i]); args[progarray->length] = NULL; @@ -186,105 +167,151 @@ java::lang::ConcreteProcess::startProcess (jstringArray progarray, env[i] = new_string (elts[i]); env[envp->length] = NULL; } - } - catch (java::lang::OutOfMemoryError *oome) - { - fail (0, args, env, NULL, NULL, NULL, NULL, oome); - throw oome; - } - // Create pipes for I/O. MSGP is for communicating exec() status. - int inp[2], outp[2], errp[2], msgp[2]; + // Create pipes for I/O. MSGP is for communicating exec() + // status. + if (pipe (inp) || pipe (outp) || pipe (errp) || pipe (msgp) + || fcntl (msgp[1], F_SETFD, FD_CLOEXEC)) + throw new IOException (JvNewStringLatin1 (strerror (errno))); - if (pipe (inp)) - fail (errno, args, env); - if (pipe (outp)) - fail (errno, args, env, inp); - if (pipe (errp)) - fail (errno, args, env, inp, outp); - if (pipe (msgp)) - fail (errno, args, env, inp, outp, errp); - if (fcntl (msgp[1], F_SETFD, FD_CLOEXEC)) - fail (errno, args, env, inp, outp, errp, msgp); - - // We create the streams before forking. Otherwise if we had an - // error while creating the streams we would have run the child with - // no way to communicate with it. - try - { + // We create the streams before forking. Otherwise if we had an + // error while creating the streams we would have run the child + // with no way to communicate with it. errorStream = new FileInputStream (new FileDescriptor (errp[0])); inputStream = new FileInputStream (new FileDescriptor (inp[0])); outputStream = new FileOutputStream (new FileDescriptor (outp[1])); - } - catch (java::lang::Throwable *t) - { - fail (0, args, env, inp, outp, errp, msgp, t); - } - // We don't use vfork() because that would cause the local - // environment to be set by the child. - if ((pid = (jlong) fork ()) == -1) - fail (errno, args, env, inp, outp, errp, msgp); + // We don't use vfork() because that would cause the local + // environment to be set by the child. + if ((pid = (jlong) fork ()) == -1) + throw new IOException (JvNewStringLatin1 (strerror (errno))); - if (pid == 0) - { - // Child process, so remap descriptors and exec. + if (pid == 0) + { + // Child process, so remap descriptors and exec. - if (envp) - { - // preserve PATH unless specified explicitly - char *path_val = getenv ("PATH"); - environ = env; - if (getenv ("PATH") == NULL) + if (envp) { - char *path_env = (char *) _Jv_Malloc (strlen (path_val) + 5 + 1); - strcpy (path_env, "PATH="); - strcat (path_env, path_val); - putenv (path_env); + // Preserve PATH and LD_LIBRARY_PATH unless specified + // explicitly. + char *path_val = getenv ("PATH"); + char *ld_path_val = getenv ("LD_LIBRARY_PATH"); + environ = env; + if (getenv ("PATH") == NULL) + { + char *path_env = (char *) _Jv_Malloc (strlen (path_val) + + 5 + 1); + strcpy (path_env, "PATH="); + strcat (path_env, path_val); + putenv (path_env); + } + if (getenv ("LD_LIBRARY_PATH") == NULL) + { + char *ld_path_env + = (char *) _Jv_Malloc (strlen (ld_path_val) + 16 + 1); + strcpy (ld_path_env, "LD_LIBRARY_PATH="); + strcat (ld_path_env, ld_path_val); + putenv (ld_path_env); + } } + + // We ignore errors from dup2 because they should never occur. + dup2 (outp[0], 0); + dup2 (inp[1], 1); + dup2 (errp[1], 2); + + // Use close and not myclose -- we're in the child, and we + // aren't worried about the possible race condition. + close (inp[0]); + close (inp[1]); + close (errp[0]); + close (errp[1]); + close (outp[0]); + close (outp[1]); + close (msgp[0]); + + execvp (args[0], args); + + // Send the parent notification that the exec failed. + char c = errno; + write (msgp[1], &c, 1); + _exit (127); } - - // We ignore errors from dup2 because they should never occur. - dup2 (outp[0], 0); - dup2 (inp[1], 1); - dup2 (errp[1], 2); - - // Use close and not myclose -- we're in the child, and we - // aren't worried about the possible race condition. - close (inp[0]); - close (inp[1]); - close (errp[0]); - close (errp[1]); - close (outp[0]); - close (outp[1]); - close (msgp[0]); - - execvp (args[0], args); - - // Send the parent notification that the exec failed. - char c = errno; - write (msgp[1], &c, 1); - _exit (127); + + // Parent. Close extra file descriptors and mark ours as + // close-on-exec. + myclose (outp[0]); + myclose (inp[1]); + myclose (errp[1]); + myclose (msgp[1]); + + char c; + int r = read (msgp[0], &c, 1); + if (r == -1) + throw new IOException (JvNewStringLatin1 (strerror (errno))); + else if (r != 0) + throw new IOException (JvNewStringLatin1 (strerror (c))); } + catch (java::lang::Throwable *thrown) + { + // Do some cleanup we only do on failure. If a stream object + // has been created, we must close the stream itself (to avoid + // duplicate closes when the stream object is collected). + // Otherwise we simply close the underlying file descriptor. + // We ignore errors here as they are uninteresting. + + try + { + if (inputStream != NULL) + inputStream->close (); + else + myclose (inp[0]); + } + catch (java::lang::Throwable *ignore) + { + } + + try + { + if (outputStream != NULL) + outputStream->close (); + else + myclose (outp[1]); + } + catch (java::lang::Throwable *ignore) + { + } + + try + { + if (errorStream != NULL) + errorStream->close (); + else + myclose (errp[0]); + } + catch (java::lang::Throwable *ignore) + { + } - // Parent. Close extra file descriptors and mark ours as - // close-on-exec. - myclose (outp[0]); - myclose (inp[1]); - myclose (errp[1]); - myclose (msgp[1]); + // These are potentially duplicate, but it doesn't matter due to + // the use of myclose. + myclose (outp[0]); + myclose (inp[1]); + myclose (errp[1]); + myclose (msgp[1]); - char c; - int r = read (msgp[0], &c, 1); - if (r == -1) - fail (errno, args, env, inp, outp, errp, msgp); - else if (r != 0) - fail (c, args, env, inp, outp, errp, msgp); + exc = thrown; + } myclose (msgp[0]); cleanup (args, env); - fcntl (outp[1], F_SETFD, FD_CLOEXEC); - fcntl (inp[0], F_SETFD, FD_CLOEXEC); - fcntl (errp[0], F_SETFD, FD_CLOEXEC); + if (exc != NULL) + throw exc; + else + { + fcntl (outp[1], F_SETFD, FD_CLOEXEC); + fcntl (inp[0], F_SETFD, FD_CLOEXEC); + fcntl (errp[0], F_SETFD, FD_CLOEXEC); + } }