Hi,

While testing eclipse I sometimes saw interrupted reads occur. VMChannel
already had a mechanism for checking the interrupted status of a thread
when a system call returned early. But this wasn't used for the read()
and write() methods. This patch adds the logic. And makes my eclipse
happy again :)

2006-12-04  Mark Wielaard  <[EMAIL PROTECTED]>

    * vm/reference/gnu/java/nio/VMChannel.java (isThreadInterrupted):
    Make static.
    * native/jni/java-nio/gnu_java_nio_VMChannel.c
    (JCL_thread_interrupted): Only take JNIEnv.
    (vm_channel_class): New static variable.
    (initID): Set vm_channel_class.
    Wrap all reads() and writes() in do-while blocks that check
    interrupted status.

Committed,

Mark
Index: native/jni/java-nio/gnu_java_nio_VMChannel.c
===================================================================
RCS file: /cvsroot/classpath/classpath/native/jni/java-nio/gnu_java_nio_VMChannel.c,v
retrieving revision 1.9
diff -u -r1.9 gnu_java_nio_VMChannel.c
--- native/jni/java-nio/gnu_java_nio_VMChannel.c	9 Nov 2006 11:26:57 -0000	1.9
+++ native/jni/java-nio/gnu_java_nio_VMChannel.c	4 Dec 2006 00:36:57 -0000
@@ -106,7 +106,7 @@
 int JCL_init_buffer(JNIEnv *, struct JCL_buffer *, jobject);
 void JCL_release_buffer(JNIEnv *, struct JCL_buffer *, jobject, jint);
 void JCL_cleanup_buffers(JNIEnv *, struct JCL_buffer *, jint, jobjectArray, jint, jlong);
-int JCL_thread_interrupted(JNIEnv *, jclass);
+int JCL_thread_interrupted(JNIEnv *);
 
 static jfieldID address_fid;
 static jmethodID get_position_mid;
@@ -117,6 +117,7 @@
 static jmethodID array_mid;
 static jmethodID array_offset_mid;
 static jmethodID thread_interrupted_mid;
+static jclass vm_channel_class;
 
 jmethodID
 get_method_id(JNIEnv *env,  jclass clazz, const char *name, 
@@ -255,9 +256,10 @@
 
 
 int
-JCL_thread_interrupted(JNIEnv *env, jclass c)
+JCL_thread_interrupted(JNIEnv *env)
 {
-  return (int) (*env)->CallBooleanMethod(env, c, thread_interrupted_mid);
+  return (int) (*env)->CallBooleanMethod(env, vm_channel_class,
+					 thread_interrupted_mid);
 }
 
 
@@ -331,7 +333,10 @@
   array_mid = get_method_id(env, byteBufferClass, "array", "()[B");
   array_offset_mid = get_method_id(env, byteBufferClass, "arrayOffset", "()I");
   
-  thread_interrupted_mid = get_method_id(env, clazz, "isThreadInterrupted", "()Z");
+  vm_channel_class = clazz;
+  thread_interrupted_mid = (*env)->GetStaticMethodID(env, clazz,
+                                                  "isThreadInterrupted",
+                                                  "()Z");
 }
 
 JNIEXPORT void JNICALL 
@@ -378,6 +383,7 @@
   jint len;
   ssize_t result;
   struct JCL_buffer buf;
+  int tmp_errno;
 
 /*   NIODBG("fd: %d; bbuf: %p", fd, bbuf); */
   
@@ -396,7 +402,13 @@
       return 0;
     }
   
-  result = cpnio_read (fd, &(buf.ptr[buf.position + buf.offset]), len);
+  do 
+    {
+      result = cpnio_read (fd, &(buf.ptr[buf.position + buf.offset]), len);
+      tmp_errno = errno;
+    }
+  while (result == -1 && errno == EINTR && ! JCL_thread_interrupted(env));
+  errno = tmp_errno;
   
   if (result == 0)
     {
@@ -452,6 +464,7 @@
   jint len;
   ssize_t result;
   struct JCL_buffer buf;
+  int tmp_errno;
 
 /*   NIODBG("fd: %d; bbuf: %p", fd, bbuf); */
   
@@ -470,7 +483,14 @@
       return 0;
     }
   
-  result = cpnio_write (fd, &(buf.ptr[buf.position + buf.offset]), len);
+  do
+    {
+      result = cpnio_write (fd, &(buf.ptr[buf.position + buf.offset]), len);
+      tmp_errno = errno;
+    }
+  while (result == -1 && errno == EINTR && ! JCL_thread_interrupted(env));
+  errno = tmp_errno;
+
   buf.count = result;
 
   if (result == -1)
@@ -524,6 +544,7 @@
   ssize_t result;
   jint vec_len = length < JCL_IOV_MAX ? length : JCL_IOV_MAX;
   jlong bytes_read = 0;
+  int tmp_errno;
 
 /*   NIODBG("fd: %d; bbufs: %p; offset: %d; length: %d", */
 /*          fd, bbufs, offset, length); */
@@ -547,7 +568,13 @@
     }
     
   /* Work the scattering magic */
-  result = cpnio_readv (fd, buffers, vec_len);
+  do
+    {
+      result = cpnio_readv (fd, buffers, vec_len);
+      tmp_errno = errno;
+    }
+  while (result == -1 && errno == EINTR && ! JCL_thread_interrupted(env));
+  errno = tmp_errno;
   bytes_read = (jlong) result;
   
   /* Handle the response */
@@ -606,6 +633,7 @@
   ssize_t result;
   jint vec_len = length < JCL_IOV_MAX ? length : JCL_IOV_MAX;
   jlong bytes_written;
+  int tmp_errno;
   
 /*   NIODBG("fd: %d; bbufs: %p; offset: %d; length: %d", */
 /*          fd, bbufs, offset, length); */
@@ -629,7 +657,14 @@
     }
     
   /* Work the gathering magic */
-  result = cpnio_writev (fd, buffers, vec_len);
+  do
+    {
+      result = cpnio_writev (fd, buffers, vec_len);
+      tmp_errno = errno;
+    }
+  while (result == -1 && tmp_errno == EINTR && ! JCL_thread_interrupted(env));
+  errno = tmp_errno;
+
   bytes_written = (jlong) result;
 
   if (result < 0)
@@ -895,10 +930,18 @@
 #ifdef HAVE_READ
   char in;
   int ret;
+  int tmp_errno;
 
 /*   NIODBG("fd: %d", fd); */
 
-  ret = cpnio_read (fd, &in, 1);
+  do
+    {
+      ret = cpnio_read (fd, &in, 1);
+      tmp_errno = errno;
+    }
+  while (ret == -1 && errno == EINTR && ! JCL_thread_interrupted(env));
+  errno = tmp_errno;
+
   if (-1 == ret)
     JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
   if (0 == ret)
@@ -925,10 +968,17 @@
 #ifdef HAVE_WRITE
   char out = (char) data;
   int ret;
+  int tmp_errno;
 
 /*   NIODBG("fd: %d; data: %d", fd, data); */
 
-  ret = cpnio_write (fd, &out, 1);
+  do
+    {
+      ret = cpnio_write (fd, &out, 1);
+      tmp_errno = errno;
+    }
+  while (ret == -1 && errno == EINTR && ! JCL_thread_interrupted(env));
+  errno = tmp_errno;
 
   if (-1 == ret)
     JCL_ThrowException(env, IO_EXCEPTION, strerror (errno));
@@ -1355,7 +1405,7 @@
  */
 JNIEXPORT jint JNICALL
 Java_gnu_java_nio_VMChannel_accept (JNIEnv *env,
-                                    jclass clazz,
+                                    jclass c __attribute__((unused)),
                                     jint fd)
 {
 #ifdef HAVE_ACCEPT
@@ -1383,7 +1433,7 @@
              * other unrelated signal interrupted the system function and
              * we should start over again.
              */
-            if (JCL_thread_interrupted(env, clazz))
+            if (JCL_thread_interrupted(env))
               {
                 JCL_ThrowException (env, "java/net/SocketException", strerror (tmp_errno));
                 return -1;
Index: vm/reference/gnu/java/nio/VMChannel.java
===================================================================
RCS file: /cvsroot/classpath/classpath/vm/reference/gnu/java/nio/VMChannel.java,v
retrieving revision 1.5
diff -u -r1.5 VMChannel.java
--- vm/reference/gnu/java/nio/VMChannel.java	25 Oct 2006 00:33:27 -0000	1.5
+++ vm/reference/gnu/java/nio/VMChannel.java	4 Dec 2006 00:36:57 -0000
@@ -634,7 +634,7 @@
    * 
    * @return
    */
-  final boolean isThreadInterrupted()
+  static boolean isThreadInterrupted()
   {
     return Thread.currentThread().isInterrupted();
   }

Reply via email to