diff options
Diffstat (limited to 'native/jni/java-nio/gnu_java_nio_VMChannel.c')
-rw-r--r-- | native/jni/java-nio/gnu_java_nio_VMChannel.c | 61 |
1 files changed, 56 insertions, 5 deletions
diff --git a/native/jni/java-nio/gnu_java_nio_VMChannel.c b/native/jni/java-nio/gnu_java_nio_VMChannel.c index 8d8aefe5d..97eb38618 100644 --- a/native/jni/java-nio/gnu_java_nio_VMChannel.c +++ b/native/jni/java-nio/gnu_java_nio_VMChannel.c @@ -372,6 +372,19 @@ Java_gnu_java_nio_VMChannel_setBlocking (JNIEnv *env, } } +/* Return true if fd is in non-blocking mode. */ +static jboolean +is_non_blocking_fd(jint fd) +{ + int opts; + opts = fcntl(fd, F_GETFL); + if (opts == -1) + { + /* Assume blocking on error. */ + return 0; + } + return (opts & O_NONBLOCK) != 0; +} JNIEXPORT jint JNICALL Java_gnu_java_nio_VMChannel_read__ILjava_nio_ByteBuffer_2 (JNIEnv *env, @@ -418,8 +431,21 @@ Java_gnu_java_nio_VMChannel_read__ILjava_nio_ByteBuffer_2 (JNIEnv *env, else if (result == -1) { buf.count = 0; - if (errno == EAGAIN) /* Non-blocking */ - result = 0; + if (errno == EAGAIN) + { + if (is_non_blocking_fd(fd)) + { + /* Non-blocking */ + result = 0; + } + else + { + /* Read timeout on a socket with SO_RCVTIMEO != 0. */ + JCL_release_buffer(env, &buf, bbuf, JNI_ABORT); + JCL_ThrowException(env, SOCKET_TIMEOUT_EXCEPTION, "read timed out"); + return -1; + } + } else if (errno == EBADF) /* Bad fd */ { JCL_release_buffer(env, &buf, bbuf, JNI_ABORT); @@ -580,8 +606,21 @@ Java_gnu_java_nio_VMChannel_readScattering (JNIEnv *env, /* Handle the response */ if (result < 0) { - if (errno == EAGAIN) /* Non blocking */ - result = 0; + if (errno == EAGAIN) + { + if (is_non_blocking_fd(fd)) + { + /* Non-blocking */ + result = 0; + } + else + { + /* Read timeout on a socket with SO_RCVTIMEO != 0. */ + JCL_cleanup_buffers(env, bi_list, vec_len, bbufs, offset, bytes_read); + JCL_ThrowException(env, SOCKET_TIMEOUT_EXCEPTION, "read timed out"); + return -1; + } + } else if (errno == EBADF) /* Bad fd */ { JCL_cleanup_buffers(env, bi_list, vec_len, bbufs, offset, bytes_read); @@ -943,7 +982,17 @@ Java_gnu_java_nio_VMChannel_read__I (JNIEnv *env, errno = tmp_errno; if (-1 == ret) - JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); + { + if (errno == EAGAIN && !is_non_blocking_fd(fd)) + { + /* Read timeout on a socket with SO_RCVTIMEO != 0. */ + JCL_ThrowException(env, SOCKET_TIMEOUT_EXCEPTION, "read timed out"); + } + else + JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); + return -1; + } + if (0 == ret) return -1; @@ -1103,6 +1152,7 @@ Java_gnu_java_nio_VMChannel_connect (JNIEnv *env, jclass clazz __attribute__((un if (EINPROGRESS == errno) { fd_set wrfds; + FD_ZERO(&wrfds); FD_SET(fd, &wrfds); ret = cpnio_select (fd + 1, NULL, &wrfds, NULL, &timeo); if (ret == -1) @@ -1227,6 +1277,7 @@ Java_gnu_java_nio_VMChannel_connect6 (JNIEnv *env, jclass clazz __attribute__((u if (EINPROGRESS == errno) { fd_set wrfds; + FD_ZERO(&wrfds); FD_SET(fd, &wrfds); ret = cpnio_select (fd + 1, NULL, &wrfds, NULL, &timeo); if (ret == -1) |