* 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
This commit is contained in:
parent
f0ede6b31c
commit
c9d126aec9
14
ChangeLog
14
ChangeLog
@ -1,3 +1,17 @@
|
||||
Fri Jun 3 23:23:02 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||
|
||||
* 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 <nagai@ai.kyutech.ac.jp>
|
||||
|
||||
* ext/tk/lib/multi-tk.rb: fix typo.
|
||||
|
172
eval.c
172
eval.c
@ -134,6 +134,10 @@ typedef jmp_buf rb_jmpbuf_t;
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_PARAM_H
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
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;\
|
||||
\
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
34
intern.h
34
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)));
|
||||
|
179
io.c
179
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 <sys/select.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* IO.select(read_array
|
||||
* [, write_array
|
||||
* [, error_array
|
||||
* [, timeout]]] ) => array or nil
|
||||
*
|
||||
* See <code>Kernel#select</code>.
|
||||
*/
|
||||
|
||||
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; i<RARRAY(read)->len; 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; i<RARRAY(write)->len; 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; i<RARRAY(except)->len; 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 <code>Kernel#select</code>.
|
||||
*/
|
||||
|
||||
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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user