6671051: (process) Runtime.exec() hangs if signalled during fork/exec
authormartin
Mon, 10 Mar 2008 14:32:51 -0700
changeset 50 a437b3f9d7f4
parent 49 b25b3ff21b7c
child 51 6fe31bc95bbc
child 53 711cd7c3af02
6671051: (process) Runtime.exec() hangs if signalled during fork/exec Reviewed-by: iris
jdk/src/solaris/native/java/lang/UNIXProcess_md.c
--- 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;