From f3d6a3bd3b1d68a51ad1d27ca91b7d8e53aaf5ba Mon Sep 17 00:00:00 2001 From: Martin Buchholz Date: Mon, 10 Mar 2008 14:32:51 -0700 Subject: [PATCH] 6671051: (process) Runtime.exec() hangs if signalled during fork/exec Reviewed-by: iris --- .../solaris/native/java/lang/UNIXProcess_md.c | 39 ++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/jdk/src/solaris/native/java/lang/UNIXProcess_md.c b/jdk/src/solaris/native/java/lang/UNIXProcess_md.c index 480298cde58..8390a2baad5 100644 --- a/jdk/src/solaris/native/java/lang/UNIXProcess_md.c +++ b/jdk/src/solaris/native/java/lang/UNIXProcess_md.c @@ -479,6 +479,37 @@ closeSafely(int fd) close(fd); } +/* + * Reads nbyte bytes from file descriptor fd into buf, + * The read operation is retried in case of EINTR or partial reads. + * + * Returns number of bytes read (normally nbyte, but may be less in + * case of EOF). In case of read errors, returns -1 and sets errno. + */ +static ssize_t +readFully(int fd, void *buf, size_t nbyte) +{ + ssize_t remaining = nbyte; + for (;;) { + ssize_t n = read(fd, buf, remaining); + if (n == 0) { + return nbyte - remaining; + } else if (n > 0) { + remaining -= n; + if (remaining <= 0) + return nbyte; + /* We were interrupted in the middle of reading the bytes. + * Unlikely, but possible. */ + buf = (void *) (((char *)buf) + n); + } else if (errno == EINTR) { + /* Strange signals like SIGJVM1 are possible at any time. + * See http://www.dreamsongs.com/WorseIsBetter.html */ + } else { + return -1; + } + } +} + #ifndef __solaris__ #undef fork1 #define fork1() fork() @@ -606,10 +637,16 @@ Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env, /* parent process */ close(fail[1]); fail[1] = -1; /* See: WhyCantJohnnyExec */ - if (read(fail[0], &errnum, sizeof(errnum)) != 0) { + + switch (readFully(fail[0], &errnum, sizeof(errnum))) { + case 0: break; /* Exec succeeded */ + case sizeof(errnum): waitpid(resultPid, NULL, 0); throwIOException(env, errnum, "Exec failed"); goto Catch; + default: + throwIOException(env, errno, "Read failed"); + goto Catch; } fds[0] = (in [1] != -1) ? in [1] : -1;