Hi,

I have found two problems about ServerSocket#accept.

(1) Even if we call setSoTimeout on a java.net.ServerSocket,
    accept() does not throw SocketTimeoutException.

(2) FreeBSD's accept does not detect timeout set by setsockopt.

And here is my patch.

ChangeLog

2007-01-25  Ito Kazumitsu  <[EMAIL PROTECTED]>

        * native/jni/java-nio/gnu_java_nio_VMChannel.c
        (Java_gnu_java_nio_VMChannel_accept): Throw SocketTimeoutException
        in case of timeout.
        * native/jni/java-nio/javanio.c(cpnio_accept): Call select() if
        SO_RCVTIMEO is set.

Index: classpath/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.14
diff -u -r1.14 gnu_java_nio_VMChannel.c
--- classpath/native/jni/java-nio/gnu_java_nio_VMChannel.c      9 Dec 2006 
06:12:15 -0000       1.14
+++ classpath/native/jni/java-nio/gnu_java_nio_VMChannel.c      24 Jan 2007 
15:30:39 -0000
@@ -1501,6 +1501,10 @@
           case EWOULDBLOCK:
 #endif
           case EAGAIN:
+            if (!is_non_blocking_fd(fd))
+              {
+                JCL_ThrowException(env, SOCKET_TIMEOUT_EXCEPTION, "Accept 
timed out");
+              }
             /* Socket in non-blocking mode and no pending connection. */
             return -1;
           default:
Index: classpath/native/jni/java-nio/javanio.c
===================================================================
RCS file: /cvsroot/classpath/classpath/native/jni/java-nio/javanio.c,v
retrieving revision 1.3
diff -u -r1.3 javanio.c
--- classpath/native/jni/java-nio/javanio.c     4 Oct 2006 10:28:36 -0000       
1.3
+++ classpath/native/jni/java-nio/javanio.c     24 Jan 2007 15:30:39 -0000
@@ -44,6 +44,7 @@
 #include <sys/types.h>
 #include <sys/fcntl.h>
 #include <sys/socket.h>
+#include <sys/select.h>
 #include <sys/uio.h>
 #include <unistd.h>
 
@@ -86,6 +87,25 @@
 CPNIO_EXPORT int
 cpnio_accept (int fd, struct sockaddr *addr, socklen_t *addrlen)
 {
+  fd_set rset;
+  struct timeval tv;
+  socklen_t tvlen = sizeof(tv);
+  int ret;
+
+  tv.tv_sec = 0;
+  tv.tv_usec = 0;
+  getsockopt (fd, SOL_SOCKET, SO_RCVTIMEO, &tv, &tvlen);
+  if (tv.tv_sec > 0 || tv.tv_usec > 0)
+    {
+      FD_ZERO(&rset);
+      FD_SET(fd,&rset);
+      ret = select (fd+1,&rset,NULL,NULL,&tv);
+      if (ret == 0)
+        {
+          errno = EAGAIN;
+          return -1;
+        }
+    }
   return accept (fd, addr, addrlen);
 }
 

Reply via email to