From c9d126aec990acb56dfa87b67e9fc312f82da91d Mon Sep 17 00:00:00 2001 From: nobu Date: Fri, 3 Jun 2005 14:23:17 +0000 Subject: * intern.h (rb_fdset_t): deal with fd bit sets over FD_SETSIZE. fixed: [ruby-dev:26187] * eval.c (rb_fd_init, rb_fd_term, rb_fd_zero, rb_fd_set, rb_fd_clr, rb_fd_isset, rb_fd_copy): ditto. * io.c (rb_io_wait_readable, rb_io_wait_writable, rb_f_select): ditto. * ext/io/wait/wait.c (io_wait): ditto. * ext/socket/socket.c (wait_connectable, unix_recv_io): ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@8552 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 14 ++++ eval.c | 172 +++++++++++++++++++++++++++++++++++++++++++------- ext/io/wait/wait.c | 37 +++++++++-- ext/socket/socket.c | 77 +++++++++++++++------- intern.h | 34 ++++++++++ io.c | 179 +++++++++++++++++++++++++++++++++++++--------------- 6 files changed, 408 insertions(+), 105 deletions(-) diff --git a/ChangeLog b/ChangeLog index 62395bfa77..dcffde0a98 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +Fri Jun 3 23:23:02 2005 Nobuyoshi Nakada + + * intern.h (rb_fdset_t): deal with fd bit sets over FD_SETSIZE. + fixed: [ruby-dev:26187] + + * eval.c (rb_fd_init, rb_fd_term, rb_fd_zero, rb_fd_set, rb_fd_clr, + rb_fd_isset, rb_fd_copy): ditto. + + * io.c (rb_io_wait_readable, rb_io_wait_writable, rb_f_select): ditto. + + * ext/io/wait/wait.c (io_wait): ditto. + + * ext/socket/socket.c (wait_connectable, unix_recv_io): ditto. + Fri Jun 3 14:06:12 2005 Hidetoshi NAGAI * ext/tk/lib/multi-tk.rb: fix typo. diff --git a/eval.c b/eval.c index 6482352e64..5a5428613d 100644 --- a/eval.c +++ b/eval.c @@ -134,6 +134,10 @@ typedef jmp_buf rb_jmpbuf_t; #include #endif +#ifdef HAVE_SYS_PARAM_H +#include +#endif + #include VALUE rb_cProc; @@ -9771,6 +9775,98 @@ enum thread_status { # endif #endif +#ifdef NFDBITS +void +rb_fd_init(fds) + volatile rb_fdset_t *fds; +{ + fds->maxfd = 0; + fds->fdset = ALLOC(fd_set); + FD_ZERO(fds->fdset); +} + +void +rb_fd_term(fds) + rb_fdset_t *fds; +{ + if (fds->fdset) free(fds->fdset); + fds->maxfd = 0; + fds->fdset = 0; +} + +void +rb_fd_zero(fds) + rb_fdset_t *fds; +{ + if (fds->fdset) { + MEMZERO(fds->fdset, fd_mask, howmany(fds->maxfd, NFDBITS)); + FD_ZERO(fds->fdset); + } +} + +void +rb_fd_set(n, fds) + int n; + rb_fdset_t *fds; +{ + int m = howmany(n + 1, NFDBITS) * sizeof(fd_mask); + int o = howmany(fds->maxfd, NFDBITS) * sizeof(fd_mask); + + if (m < sizeof(fd_set)) m = sizeof(fd_set); + if (o < sizeof(fd_set)) o = sizeof(fd_set); + + if (m > o) { + fds->fdset = realloc(fds->fdset, m); + memset((char *)fds->fdset + o, 0, m - o); + } + if (n >= fds->maxfd) fds->maxfd = n + 1; + FD_SET(n, fds->fdset); +} + +void +rb_fd_clr(n, fds) + int n; + rb_fdset_t *fds; +{ + if (n >= fds->maxfd) return; + FD_CLR(n, fds->fdset); +} + +int +rb_fd_isset(n, fds) + int n; + const rb_fdset_t *fds; +{ + if (n >= fds->maxfd) return 0; + return FD_ISSET(n, fds->fdset); +} + +void +rb_fd_copy(dst, src, max) + rb_fdset_t *dst; + const fd_set *src; + int max; +{ + int size = howmany(max, NFDBITS) * sizeof(fd_mask); + + if (size < sizeof(fd_set)) size = sizeof(fd_set); + dst->maxfd = max; + dst->fdset = realloc(dst->fdset, size); + memcpy(dst->fdset, src, size); +} + +#undef FD_ZERO +#undef FD_SET +#undef FD_CLR +#undef FD_ISSET + +#define FD_ZERO(f) rb_fd_zero(f) +#define FD_SET(i, f) rb_fd_set(i, f) +#define FD_CLR(i, f) rb_fd_clr(i, f) +#define FD_ISSET(i, f) rb_fd_isset(i, f) + +#endif + /* typedef struct thread * rb_thread_t; */ struct thread { @@ -9817,9 +9913,9 @@ struct thread { enum thread_status status; int wait_for; int fd; - fd_set readfds; - fd_set writefds; - fd_set exceptfds; + rb_fdset_t readfds; + rb_fdset_t writefds; + rb_fdset_t exceptfds; int select_value; double delay; rb_thread_t join; @@ -9857,9 +9953,9 @@ struct thread_status_t { enum thread_status status; int wait_for; int fd; - fd_set readfds; - fd_set writefds; - fd_set exceptfds; + rb_fdset_t readfds; + rb_fdset_t writefds; + rb_fdset_t exceptfds; int select_value; double delay; rb_thread_t join; @@ -9882,6 +9978,9 @@ struct thread_status_t { (dst)->readfds = (src)->readfds, \ (dst)->writefds = (src)->writefds, \ (dst)->exceptfds = (src)->exceptfds, \ + rb_fd_init(&(src)->readfds), \ + rb_fd_init(&(src)->writefds), \ + rb_fd_init(&(src)->exceptfds), \ (dst)->select_value = (src)->select_value, \ (dst)->delay = (src)->delay, \ (dst)->join = (src)->join, \ @@ -10110,6 +10209,9 @@ thread_free(th) if (th->prev) th->prev->next = th->next; if (th->next) th->next->prev = th->prev; } + rb_fd_term(&th->readfds); + rb_fd_term(&th->writefds); + rb_fd_term(&th->exceptfds); if (th != main_thread) free(th); } @@ -10433,12 +10535,13 @@ rb_thread_deadlock() static void copy_fds(dst, src, max) - fd_set *dst, *src; + rb_fdset_t *dst, *src; int max; { int n = 0; int i; + if (max >= rb_fd_max(src)) max = rb_fd_max(src) - 1; for (i=0; i<=max; i++) { if (FD_ISSET(i, src)) { n = i; @@ -10449,11 +10552,13 @@ copy_fds(dst, src, max) static int match_fds(dst, src, max) - fd_set *dst, *src; + rb_fdset_t *dst, *src; int max; { int i; + if (max >= rb_fd_max(src)) max = rb_fd_max(src) - 1; + if (max >= rb_fd_max(dst)) max = rb_fd_max(dst) - 1; for (i=0; i<=max; i++) { if (FD_ISSET(i, src) && FD_ISSET(i, dst)) { return Qtrue; @@ -10464,11 +10569,12 @@ match_fds(dst, src, max) static int intersect_fds(src, dst, max) - fd_set *src, *dst; + rb_fdset_t *src, *dst; int max; { int i, n = 0; + if (max >= rb_fd_max(dst)) max = rb_fd_max(dst) - 1; for (i=0; i<=max; i++) { if (FD_ISSET(i, dst)) { if (FD_ISSET(i, src)) { @@ -10486,11 +10592,12 @@ intersect_fds(src, dst, max) static int find_bad_fds(dst, src, max) - fd_set *dst, *src; + rb_fdset_t *dst, *src; int max; { int i, test = Qfalse; + if (max >= rb_fd_max(src)) max = rb_fd_max(src) - 1; for (i=0; i<=max; i++) { if (FD_ISSET(i, src) && !FD_ISSET(i, dst)) { FD_CLR(i, src); @@ -10508,9 +10615,9 @@ rb_thread_schedule() rb_thread_t curr; int found = 0; - fd_set readfds; - fd_set writefds; - fd_set exceptfds; + rb_fdset_t readfds; + rb_fdset_t writefds; + rb_fdset_t exceptfds; struct timeval delay_tv, *delay_ptr; double delay, now; /* OK */ int n, max; @@ -10534,6 +10641,10 @@ rb_thread_schedule() curr = curr->prev; } + rb_fd_init(&readfds); + rb_fd_init(&writefds); + rb_fd_init(&exceptfds); + again: max = -1; FD_ZERO(&readfds); @@ -10607,11 +10718,20 @@ rb_thread_schedule() delay_ptr = &delay_tv; } - n = select(max+1, &readfds, &writefds, &exceptfds, delay_ptr); + n = select(max+1, rb_fd_ptr(&readfds), rb_fd_ptr(&writefds), rb_fd_ptr(&exceptfds), delay_ptr); if (n < 0) { int e = errno; - if (rb_trap_pending) rb_trap_exec(); + if (rb_trap_pending) { + int status; + rb_protect((VALUE (*)_((VALUE)))rb_trap_exec, Qnil, &status); + if (status) { + rb_fd_term(&readfds); + rb_fd_term(&writefds); + rb_fd_term(&exceptfds); + rb_jump_tag(status); + } + } if (e == EINTR) goto again; #ifdef ERESTART if (e == ERESTART) goto again; @@ -10682,6 +10802,10 @@ rb_thread_schedule() goto again; } + rb_fd_term(&readfds); + rb_fd_term(&writefds); + rb_fd_term(&exceptfds); + FOREACH_THREAD_FROM(curr, th) { if (th->status == THREAD_TO_KILL) { next = th; @@ -10909,11 +11033,11 @@ rb_thread_select(max, read, write, except, timeout) } curr_thread->status = THREAD_STOPPED; - if (read) curr_thread->readfds = *read; + if (read) rb_fd_copy(&curr_thread->readfds, read, max); else FD_ZERO(&curr_thread->readfds); - if (write) curr_thread->writefds = *write; + if (write) rb_fd_copy(&curr_thread->writefds, write, max); else FD_ZERO(&curr_thread->writefds); - if (except) curr_thread->exceptfds = *except; + if (except) rb_fd_copy(&curr_thread->exceptfds, except, max); else FD_ZERO(&curr_thread->exceptfds); curr_thread->fd = max; curr_thread->wait_for = WAIT_SELECT; @@ -10923,9 +11047,9 @@ rb_thread_select(max, read, write, except, timeout) curr_thread->wait_for |= WAIT_TIME; } rb_thread_schedule(); - if (read) *read = curr_thread->readfds; - if (write) *write = curr_thread->writefds; - if (except) *except = curr_thread->exceptfds; + if (read) *read = *rb_fd_ptr(&curr_thread->readfds); + if (write) *write = *rb_fd_ptr(&curr_thread->writefds); + if (except) *except = *rb_fd_ptr(&curr_thread->exceptfds); return curr_thread->select_value; } @@ -11567,9 +11691,9 @@ rb_thread_group(thread) th->wait_for = 0;\ IA64_INIT(th->bstr_ptr = 0);\ IA64_INIT(th->bstr_len = 0);\ - FD_ZERO(&th->readfds);\ - FD_ZERO(&th->writefds);\ - FD_ZERO(&th->exceptfds);\ + rb_fd_init(&th->readfds);\ + rb_fd_init(&th->writefds);\ + rb_fd_init(&th->exceptfds);\ th->delay = 0.0;\ th->join = 0;\ \ diff --git a/ext/io/wait/wait.c b/ext/io/wait/wait.c index df8d24c29b..fcb3bcfe42 100644 --- a/ext/io/wait/wait.c +++ b/ext/io/wait/wait.c @@ -50,6 +50,23 @@ io_ready_p(io) return Qnil; } +struct wait_readable_arg { + rb_fdset_t fds; + struct timeval *timeout; +}; + +#ifdef HAVE_RB_FD_INIT +static VALUE +wait_readable(p) + VALUE p; +{ + struct wait_readable_arg *arg = (struct wait_readable_arg *)p; + rb_fdset_t *fds = &arg->fds; + + return (VALUE)rb_thread_select(rb_fd_max(fds), rb_fd_ptr(fds), NULL, NULL, arg->timeout); +} +#endif + /* =begin --- IO#wait([timeout]) @@ -64,27 +81,33 @@ io_wait(argc, argv, io) VALUE io; { OpenFile *fptr; - fd_set rd; + struct wait_readable_arg arg; int fd, n; VALUE timeout; - struct timeval *tp, timerec; + struct timeval timerec; GetOpenFile(io, fptr); rb_io_check_readable(fptr); rb_scan_args(argc, argv, "01", &timeout); if (NIL_P(timeout)) { - tp = 0; + arg.timeout = 0; } else { timerec = rb_time_interval(timeout); - tp = &timerec; + arg.timeout = &timerec; } if (rb_io_read_pending(fptr)) return Qtrue; fd = fptr->fd; - FD_ZERO(&rd); - FD_SET(fd, &rd); - if (rb_thread_select(fd + 1, &rd, NULL, NULL, tp) < 0) + rb_fd_init(&arg.fds); + rb_fd_set(fd, &arg.fds); +#ifdef HAVE_RB_FD_INIT + n = (int)rb_ensure(wait_readable, (VALUE)&arg, + (VALUE (*)_((VALUE)))rb_fd_term, (VALUE)&arg.fds); +#else + n = rb_thread_select(fd + 1, rb_fd_ptr(&rd), NULL, NULL, tp) +#endif + if (n < 0) rb_sys_fail(0); rb_io_check_closed(fptr); if (ioctl(fptr->fd, FIONREAD, &n)) rb_sys_fail(0); diff --git a/ext/socket/socket.c b/ext/socket/socket.c index 9383580bdf..d4fd620a00 100644 --- a/ext/socket/socket.c +++ b/ext/socket/socket.c @@ -888,26 +888,25 @@ ruby_socket(domain, type, proto) } static int -wait_connectable(fd) +wait_connectable0(fd, fds_w, fds_e) int fd; + rb_fdset_t *fds_w, *fds_e; { int sockerr, sockerrlen; - fd_set fds_w; - fd_set fds_e; for (;;) { - FD_ZERO(&fds_w); - FD_ZERO(&fds_e); + rb_fd_zero(fds_w); + rb_fd_zero(fds_e); - FD_SET(fd, &fds_w); - FD_SET(fd, &fds_e); + rb_fd_set(fd, fds_w); + rb_fd_set(fd, fds_e); - rb_thread_select(fd+1, 0, &fds_w, &fds_e, 0); + rb_thread_select(fd+1, 0, rb_fd_ptr(fds_w), rb_fd_ptr(fds_e), 0); - if (FD_ISSET(fd, &fds_w)) { + if (rb_fd_isset(fd, fds_w)) { return 0; } - else if (FD_ISSET(fd, &fds_e)) { + else if (rb_fd_isset(fd, fds_e)) { sockerrlen = sizeof(sockerr); if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&sockerr, &sockerrlen) == 0) { @@ -922,6 +921,49 @@ wait_connectable(fd) return 0; } +struct wait_connectable_arg { + int fd; + rb_fdset_t fds_w; + rb_fdset_t fds_e; +}; + +#ifdef HAVE_RB_FD_INIT +static VALUE +try_wait_connectable(arg) + VALUE arg; +{ + struct wait_connectable_arg *p = (struct wait_connectable_arg *)arg; + return (VALUE)wait_connectable0(p->fd, &p->fds_w, &p->fds_e); +} + +static VALUE +wait_connectable_ensure(arg) + VALUE arg; +{ + struct wait_connectable_arg *p = (struct wait_connectable_arg *)arg; + rb_fd_term(&p->fds_w); + rb_fd_term(&p->fds_e); + return Qnil; +} +#endif + +static int +wait_connectable(fd) + int fd; +{ + struct wait_connectable_arg arg; + + rb_fd_init(&arg.fds_w); + rb_fd_init(&arg.fds_e); +#ifdef HAVE_RB_FD_INIT + arg.fd = fd; + return (int)rb_ensure(try_wait_connectable, (VALUE)&arg, + wait_connectable_ensure,(VALUE)&arg); +#else + return wait_connectable0(fd, &arg.fds_w, &arg.fds_e); +#endif +} + #ifdef __CYGWIN__ #define WAIT_IN_PROGRESS 10 #endif @@ -1734,19 +1776,6 @@ unix_send_io(sock, val) #endif } -#if defined(HAVE_RECVMSG) && (FD_PASSING_BY_MSG_CONTROL || FD_PASSING_BY_MSG_ACCRIGHTS) -static void -thread_read_select(fd) - int fd; -{ - fd_set fds; - - FD_ZERO(&fds); - FD_SET(fd, &fds); - rb_thread_select(fd+1, &fds, 0, 0, 0); -} -#endif - static VALUE unix_recv_io(argc, argv, sock) int argc; @@ -1776,7 +1805,7 @@ unix_recv_io(argc, argv, sock) GetOpenFile(sock, fptr); - thread_read_select(fptr->fd); + rb_io_wait_readable(fptr->fd); msg.msg_name = NULL; msg.msg_namelen = 0; diff --git a/intern.h b/intern.h index 221e223b05..d4b5d8bff3 100644 --- a/intern.h +++ b/intern.h @@ -145,6 +145,40 @@ NORETURN(void rb_load_fail _((const char*))); NORETURN(void rb_error_frozen _((const char*))); void rb_check_frozen _((VALUE)); /* eval.c */ +#ifdef NFDBITS +typedef struct { + int maxfd; + fd_set *fdset; +} rb_fdset_t; + +#define HAVE_RB_FD_INIT 1 + +void rb_fd_init _((volatile rb_fdset_t *)); +void rb_fd_term _((rb_fdset_t *)); +void rb_fd_zero _((rb_fdset_t *)); +void rb_fd_set _((int, rb_fdset_t *)); +void rb_fd_clr _((int, rb_fdset_t *)); +int rb_fd_isset _((int, const rb_fdset_t *)); +void rb_fd_copy _((rb_fdset_t *, const fd_set *, int)); + +#define rb_fd_ptr(f) ((f)->fdset) +#define rb_fd_max(f) ((f)->maxfd) + +#else + +typedef fd_set rb_fdset_t; +#define rb_fd_zero(f) FD_ZERO(f) +#define rb_fd_set(n, f) FD_SET(n, f) +#define rb_fd_clr(n, f) FD_CLR(n, f) +#define rb_fd_isset(n, f) FD_ISSET(n, f) +#define rb_fd_copy(d, s, n) (*(d) = *(s)) +#define rb_fd_ptr(f) (f) +#define rb_fd_init(f) FD_ZERO(f) +#define rb_fd_term(f) (f) +#define rb_fd_max(f) FD_SETSIZE + +#endif + RUBY_EXTERN struct RNode *ruby_current_node; void ruby_set_current_source _((void)); NORETURN(void rb_exc_raise _((VALUE))); diff --git a/io.c b/io.c index 0b137ff795..6546e75212 100644 --- a/io.c +++ b/io.c @@ -410,11 +410,22 @@ io_fflush(fptr) return -1; } +#ifdef HAVE_RB_FD_INIT +static VALUE +wait_readable(p) + VALUE p; +{ + rb_fdset_t *rfds = (rb_fdset_t *)p; + + return rb_thread_select(rb_fd_max(rfds), rb_fd_ptr(rfds), NULL, NULL, NULL); +} +#endif + int rb_io_wait_readable(f) int f; { - fd_set rfds; + rb_fdset_t rfds; switch (errno) { case EINTR: @@ -428,9 +439,14 @@ rb_io_wait_readable(f) #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN case EWOULDBLOCK: #endif - FD_ZERO(&rfds); - FD_SET(f, &rfds); + rb_fd_init(&rfds); + rb_fd_set(f, &rfds); +#ifdef HAVE_RB_FD_INIT + rb_ensure(wait_readable, (VALUE)&rfds, + (VALUE (*)_((VALUE)))rb_fd_term, (VALUE)&rfds); +#else rb_thread_select(f + 1, &rfds, NULL, NULL, NULL); +#endif return Qtrue; default: @@ -438,11 +454,22 @@ rb_io_wait_readable(f) } } +#ifdef HAVE_RB_FD_INIT +static VALUE +wait_writable(p) + VALUE p; +{ + rb_fdset_t *wfds = (rb_fdset_t *)p; + + return rb_thread_select(rb_fd_max(wfds), NULL, rb_fd_ptr(wfds), NULL, NULL); +} +#endif + int rb_io_wait_writable(f) int f; { - fd_set wfds; + rb_fdset_t wfds; switch (errno) { case EINTR: @@ -456,9 +483,14 @@ rb_io_wait_writable(f) #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN case EWOULDBLOCK: #endif - FD_ZERO(&wfds); - FD_SET(f, &wfds); + rb_fd_init(&wfds); + rb_fd_set(f, &wfds); +#ifdef HAVE_RB_FD_INIT + rb_ensure(wait_writable, (VALUE)&wfds, + (VALUE (*)_((VALUE)))rb_fd_term, (VALUE)&wfds); +#else rb_thread_select(f + 1, NULL, &wfds, NULL, NULL); +#endif return Qtrue; default: @@ -2617,11 +2649,11 @@ rb_fdopen(fd, mode) #endif file = fdopen(fd, mode); if (!file) { + if ( #if defined(sun) - if (errno == 0 || errno == EMFILE || errno == ENFILE) { -#else - if (errno == EMFILE || errno == ENFILE) { + errno == 0 || #endif + errno == EMFILE || errno == ENFILE) { rb_gc(); #if defined(sun) errno = 0; @@ -4511,52 +4543,29 @@ rb_f_backquote(obj, str) #include #endif -/* - * call-seq: - * IO.select(read_array - * [, write_array - * [, error_array - * [, timeout]]] ) => array or nil - * - * See Kernel#select. - */ - static VALUE -rb_f_select(argc, argv, obj) - int argc; - VALUE *argv; - VALUE obj; +select_internal(read, write, except, tp, fds) + VALUE read, write, except; + struct timeval *tp; + rb_fdset_t *fds; { - VALUE read, write, except, timeout, res, list; - fd_set rset, wset, eset, pset; + VALUE res, list; fd_set *rp, *wp, *ep; - struct timeval *tp, timerec; OpenFile *fptr; long i; int max = 0, n; int interrupt_flag = 0; int pending = 0; + struct timeval timerec; - rb_scan_args(argc, argv, "13", &read, &write, &except, &timeout); - if (NIL_P(timeout)) { - tp = 0; - } - else { - timerec = rb_time_interval(timeout); - tp = &timerec; - } - - FD_ZERO(&pset); if (!NIL_P(read)) { Check_Type(read, T_ARRAY); - rp = &rset; - FD_ZERO(rp); for (i=0; ilen; i++) { GetOpenFile(rb_io_get_io(RARRAY(read)->ptr[i]), fptr); - FD_SET(fptr->fd, rp); + rb_fd_set(fptr->fd, &fds[0]); if (READ_DATA_PENDING(fptr)) { /* check for buffered data */ pending++; - FD_SET(fptr->fd, &pset); + rb_fd_set(fptr->fd, &fds[3]); } if (max < fptr->fd) max = fptr->fd; } @@ -4564,32 +4573,31 @@ rb_f_select(argc, argv, obj) timerec.tv_sec = timerec.tv_usec = 0; tp = &timerec; } + rp = rb_fd_ptr(&fds[0]); } else rp = 0; if (!NIL_P(write)) { Check_Type(write, T_ARRAY); - wp = &wset; - FD_ZERO(wp); for (i=0; ilen; i++) { GetOpenFile(rb_io_get_io(RARRAY(write)->ptr[i]), fptr); - FD_SET(fptr->fd, wp); + rb_fd_set(fptr->fd, &fds[1]); if (max < fptr->fd) max = fptr->fd; } + wp = rb_fd_ptr(&fds[1]); } else wp = 0; if (!NIL_P(except)) { Check_Type(except, T_ARRAY); - ep = &eset; - FD_ZERO(ep); for (i=0; ilen; i++) { GetOpenFile(rb_io_get_io(RARRAY(except)->ptr[i]), fptr); - FD_SET(fptr->fd, ep); + rb_fd_set(fptr->fd, &fds[2]); if (max < fptr->fd) max = fptr->fd; } + ep = rb_fd_ptr(&fds[2]); } else { ep = 0; @@ -4613,8 +4621,8 @@ rb_f_select(argc, argv, obj) list = RARRAY(res)->ptr[0]; for (i=0; i< RARRAY(read)->len; i++) { GetOpenFile(rb_io_get_io(RARRAY(read)->ptr[i]), fptr); - if (FD_ISSET(fptr->fd, rp) - || FD_ISSET(fptr->fd, &pset)) { + if (rb_fd_isset(fptr->fd, &fds[0]) || + rb_fd_isset(fptr->fd, &fds[3])) { rb_ary_push(list, rb_ary_entry(read, i)); } } @@ -4624,7 +4632,7 @@ rb_f_select(argc, argv, obj) list = RARRAY(res)->ptr[1]; for (i=0; i< RARRAY(write)->len; i++) { GetOpenFile(rb_io_get_io(RARRAY(write)->ptr[i]), fptr); - if (FD_ISSET(fptr->fd, wp)) { + if (rb_fd_isset(fptr->fd, &fds[1])) { rb_ary_push(list, rb_ary_entry(write, i)); } } @@ -4634,7 +4642,7 @@ rb_f_select(argc, argv, obj) list = RARRAY(res)->ptr[2]; for (i=0; i< RARRAY(except)->len; i++) { GetOpenFile(rb_io_get_io(RARRAY(except)->ptr[i]), fptr); - if (FD_ISSET(fptr->fd, ep)) { + if (rb_fd_isset(fptr->fd, &fds[2])) { rb_ary_push(list, rb_ary_entry(except, i)); } } @@ -4644,6 +4652,77 @@ rb_f_select(argc, argv, obj) return res; /* returns an empty array on interrupt */ } +struct select_args { + VALUE read, write, except; + struct timeval *timeout; + rb_fdset_t fdsets[4]; +}; + +#ifdef HAVE_RB_FD_INIT +static VALUE +select_call(arg) + VALUE arg; +{ + struct select_args *p = (struct select_args *)arg; + + return select_internal(p->read, p->write, p->except, p->timeout, p->fdsets); +} + +static VALUE +select_end(arg) + VALUE arg; +{ + struct select_args *p = (struct select_args *)arg; + int i; + + for (i = 0; i < sizeof(p->fdsets) / sizeof(p->fdsets[0]); ++i) + rb_fd_term(&p->fdsets[i]); + return Qnil; +} +#endif + +/* + * call-seq: + * IO.select(read_array + * [, write_array + * [, error_array + * [, timeout]]] ) => array or nil + * + * See Kernel#select. + */ + +static VALUE +rb_f_select(argc, argv, obj) + int argc; + VALUE *argv; + VALUE obj; +{ + VALUE timeout; + struct select_args args; + struct timeval timerec; + int i; + + rb_scan_args(argc, argv, "13", &args.read, &args.write, &args.except, &timeout); + if (NIL_P(timeout)) { + args.timeout = 0; + } + else { + timerec = rb_time_interval(timeout); + args.timeout = &timerec; + } + + for (i = 0; i < sizeof(args.fdsets) / sizeof(args.fdsets[0]); ++i) + rb_fd_init(&args.fdsets[i]); + +#ifdef HAVE_RB_FD_INIT + return rb_ensure(select_call, (VALUE)&args, select_end, (VALUE)&args); +#else + return select_internal(args.read, args.write, args.except, + args.timeout, args.fdsets); +#endif + +} + #if !defined(MSDOS) && !defined(__human68k__) static int io_cntl(fd, cmd, narg, io_p) -- cgit v1.2.3