My new mauve test for the HTTP timeout patch I posed earlier this week was failing miserably for me with jamvm/FC6-x86_64. I turns out the the native socket code was slightly lacking. This patch fixes it up some.

I will commit both this patch and the HTTP timeout patch after another round of testing and if no objections are raised.

2006-12-08  David Daney  <[EMAIL PROTECTED]>

   * native/jni/java-nio/gnu_java_nio_VMChannel.c (is_non_blocking_fd):
   New method.
   (Java_gnu_java_nio_VMChannel_read__ILjava_nio_ByteBuffer_2): Throw
   SocketTimeoutException if a blocking socket timesout.
   (Java_gnu_java_nio_VMChannel_readScattering): Same.
   (Java_gnu_java_nio_VMChannel_read__I): Same.
   (Java_gnu_java_nio_VMChannel_connect): Initialize the fd set.
   (Java_gnu_java_nio_VMChannel_connect6): Same.

Index: native/jni/java-nio/gnu_java_nio_VMChannel.c
===================================================================
RCS file: /sources/classpath/classpath/native/jni/java-nio/gnu_java_nio_VMChannel.c,v
retrieving revision 1.12
diff -u -p -r1.12 gnu_java_nio_VMChannel.c
--- native/jni/java-nio/gnu_java_nio_VMChannel.c	4 Dec 2006 20:13:12 -0000	1.12
+++ native/jni/java-nio/gnu_java_nio_VMChannel.c	8 Dec 2006 18:59:32 -0000
@@ -372,6 +372,20 @@ Java_gnu_java_nio_VMChannel_setBlocking 
     }  
 }
 
+  /*
+   */
+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 +432,21 @@ Java_gnu_java_nio_VMChannel_read__ILjava
   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 +607,21 @@ Java_gnu_java_nio_VMChannel_readScatteri
   /* 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 +983,17 @@ Java_gnu_java_nio_VMChannel_read__I (JNI
   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 +1153,7 @@ Java_gnu_java_nio_VMChannel_connect (JNI
       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 +1278,7 @@ Java_gnu_java_nio_VMChannel_connect6 (JN
       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)

Reply via email to