summaryrefslogtreecommitdiff
path: root/native/jni/java-nio/gnu_java_nio_VMChannel.c
diff options
context:
space:
mode:
Diffstat (limited to 'native/jni/java-nio/gnu_java_nio_VMChannel.c')
-rw-r--r--native/jni/java-nio/gnu_java_nio_VMChannel.c61
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)