Hi,

At Wed, 25 May 2005 15:28:08 +0900,
nobuyoshi nakada wrote in [ruby-core:05090]:
> > In eval.c, select is used to synchronize IO in ruby threads, but on some
> > platforms select() does not work on non-sockets.  We are told that
> > Windows is just such a platform.  However, there are no exceptions in
> > the code to handle the Windows case, which is a bit puzzling.
> > Apparently, by some accident of the Windows select() implementation,
> 
> It is replaced within win32/win32.[ch].

Like the following patch, though I haven't even done compilation.

BTW, I feel that SIZEOF_LONG_LONG must be a preprocess time constant
and should be in config.h.


Index: configure.in =================================================================== RCS file: /cvs/ruby/src/ruby/configure.in,v retrieving revision 1.277 diff -U2 -p -u -r1.277 configure.in --- configure.in 15 May 2005 09:56:49 -0000 1.277 +++ configure.in 25 May 2005 09:14:34 -0000 @@ -1393,4 +1393,7 @@ case "$target_os" in esac ;; + vms) + AC_LIBOBJ([vms]) + ;; *) ;; Index: vms/vms.c =================================================================== RCS file: vms/vms.c diff -N vms/vms.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ vms/vms.c 25 May 2005 09:05:18 -0000 @@ -0,0 +1,87 @@ +#include "ruby.h" +#include "defines.h" + +static int +is_socket(int fd) +{ + int type, len; + + len = sizeof(type); + if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (void *)&type, &len) == 0) + return 1; + if (errno == ENOTSOCK) errno = 0; + + return 0; +} + +#undef select +int +rb_vms_select(int maxfd, fd_set *rfd, fd_set *wfd, fd_set *efd, struct timeval *tv) +{ + int i, maxsock, socks, nsocks; + fd_set rs, ws, es, *rp, *wp, *ep; + struct timeval z; + + FD_ZERO(&rs); + FD_ZERO(&ws); + FD_ZERO(&es); + + /* count socket and non-socket fds */ + maxsock = socks = nsocks = 0; + if (rfd || wfd || efd) { + for (i = 0; i < maxfd; ++i) { + int r = (rfd != 0) && FD_ISSET(i, rfd); + int w = (wfd != 0) && FD_ISSET(i, wfd); + int e = (efd != 0) && FD_ISSET(i, efd); + if (!r && !w && !e) continue; + if (is_socket(i)) { + if (r) FD_SET(i, (rp = &rs)); + if (w) FD_SET(i, (wp = &ws)); + if (e) FD_SET(i, (ep = &es)); + maxsock = i + 1; + socks++; + } + else { + nsocks++; + } + } + } + + if (!nsocks) { + /* sockets only */ + return select(maxsock, rfd, wfd, efd, tv); + } + + if (!socks) { + /* assuming non-socket fds are always ready */ + return nsocks; + } + + /* check if sockets are ready */ + z.tv_sec = 0; + z.tv_usec = 0; + ret = select(maxsock, rp, wp, ep, &z); + if (ret < 0) { + if (rfd) *rfd = rs; + if (wfd) *wfd = ws; + if (efd) *efd = es; + return nsocks; + } + + for (i = 0; i < maxsock; ++i) { + if (rp && FD_ISSET(i, rp)) { + FD_SET(i, rfd); + ret++; + } + if (wp && FD_ISSET(i, wp)) { + FD_SET(i, wfd); + ret++; + } + if (ep && FD_ISSET(i, ep)) { + FD_SET(i, efd); + ret++; + } + } + + return ret; +} Index: vms/vms.h =================================================================== RCS file: /cvs/ruby/src/ruby/vms/vms.h,v retrieving revision 1.3 diff -U2 -p -r1.3 vms.h --- vms/vms.h 26 Dec 2003 01:38:31 -0000 1.3 +++ vms/vms.h 25 May 2005 09:05:58 -0000 @@ -10,4 +10,7 @@ extern int vsnprintf(); extern int snprintf(); +int rb_vms_select(int, fd_set*, fd_set*, fd_set*, struct timeval*); +#define select(n, r, w, e, t) rb_vms_select(n, r, w, e, t) + #define LONG_LONG long long #define SIZEOF_LONG_LONG sizeof(long long)
-- Nobu Nakada