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);
}