6671051: (process) Runtime.exec() hangs if signalled during fork/exec

Reviewed-by: iris
This commit is contained in:
Martin Buchholz 2008-03-10 14:32:51 -07:00
parent 4385dbf930
commit f3d6a3bd3b

View File

@ -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;