6671051: (process) Runtime.exec() hangs if signalled during fork/exec
Reviewed-by: iris
--- a/jdk/src/solaris/native/java/lang/UNIXProcess_md.c Mon Mar 10 14:32:51 2008 -0700
+++ b/jdk/src/solaris/native/java/lang/UNIXProcess_md.c Mon Mar 10 14:32:51 2008 -0700
@@ -479,6 +479,37 @@
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 @@
/* 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;