Feature #16597 » 0010-select_with_poll-do-not-reaise-exception-on-bad-fd.patch
| include/ruby/internal/intern/select.h | ||
|---|---|---|
|
struct timeval;
|
||
|
int rb_thread_fd_select(int, rb_fdset_t *, rb_fdset_t *, rb_fdset_t *, rb_fdset_t *, struct timeval *);
|
||
|
int rb_thread_fd_select(int, rb_fdset_t *, rb_fdset_t *, rb_fdset_t *, rb_fdset_t *, struct timeval *, _Bool);
|
||
|
RBIMPL_SYMBOL_EXPORT_END()
|
||
| include/ruby/internal/intern/select/largesize.h | ||
|---|---|---|
|
int rb_fd_isset(int, const rb_fdset_t *);
|
||
|
void rb_fd_copy(rb_fdset_t *, const fd_set *, int);
|
||
|
void rb_fd_dup(rb_fdset_t *dst, const rb_fdset_t *src);
|
||
|
int rb_fd_select(int, rb_fdset_t *, rb_fdset_t *, rb_fdset_t *, rb_fdset_t *, struct timeval *);
|
||
|
int rb_fd_select(int, rb_fdset_t *, rb_fdset_t *, rb_fdset_t *, rb_fdset_t *, struct timeval *, _Bool);
|
||
|
RBIMPL_SYMBOL_EXPORT_END()
|
||
|
RBIMPL_ATTR_NONNULL(())
|
||
| include/ruby/internal/intern/select/win32.h | ||
|---|---|---|
|
}
|
||
|
static inline int
|
||
|
rb_fd_select(int n, rb_fdset_t *rfds, rb_fdset_t *wfds, rb_fdset_t *efds, rb_fdset_t *errfds, struct timeval *timeout)
|
||
|
rb_fd_select(int n, rb_fdset_t *rfds, rb_fdset_t *wfds, rb_fdset_t *efds, rb_fdset_t *errfds, struct timeval *timeout, _Bool select_iface)
|
||
|
{
|
||
|
return rb_w32_select(
|
||
|
n,
|
||
| include/ruby/io.h | ||
|---|---|---|
|
# define RB_WAITFD_IN POLLIN
|
||
|
# define RB_WAITFD_PRI POLLPRI
|
||
|
# define RB_WAITFD_OUT POLLOUT
|
||
|
# define RB_WAITFD_ERR (POLLHUP|POLLERR)
|
||
|
# define RB_WAITFD_ERR (POLLHUP|POLLERR|POLLNVAL)
|
||
|
#else
|
||
|
# define RB_WAITFD_IN 0x001
|
||
|
# define RB_WAITFD_PRI 0x002
|
||
| internal/io.h | ||
|---|---|---|
|
#define POLLIN_SET (POLLRDNORM | POLLRDBAND | POLLIN)
|
||
|
#define POLLOUT_SET (POLLWRBAND | POLLWRNORM | POLLOUT)
|
||
|
#define POLLEX_SET (POLLPRI)
|
||
|
#define POLLERR_SET (POLLHUP | POLLERR)
|
||
|
#define POLLERR_SET (POLLHUP | POLLERR | POLLNVAL)
|
||
|
#endif
|
||
|
/* io.c */
|
||
| io.c | ||
|---|---|---|
|
#endif
|
||
|
static VALUE
|
||
|
select_internal(VALUE read, VALUE write, VALUE except, VALUE error, struct timeval *tp, rb_fdset_t *fds)
|
||
|
select_internal(VALUE read, VALUE write, VALUE except, VALUE error, struct timeval *tp, bool select_iface, rb_fdset_t *fds)
|
||
|
{
|
||
|
VALUE res, list;
|
||
|
rb_fdset_t *rp, *wp, *ep, *erp;
|
||
| ... | ... | |
|
ep = 0;
|
||
|
}
|
||
|
if (!NIL_P(error)) {
|
||
|
if (!NIL_P(error) && !select_iface) {
|
||
|
Check_Type(error, T_ARRAY);
|
||
|
for (i=0; i<RARRAY_LEN(error); i++) {
|
||
|
VALUE io = rb_io_get_io(RARRAY_AREF(error, i));
|
||
| ... | ... | |
|
max++;
|
||
|
n = rb_thread_fd_select(max, rp, wp, ep, erp, tp);
|
||
|
n = rb_thread_fd_select(max, rp, wp, ep, erp, tp, select_iface);
|
||
|
if (n < 0) {
|
||
|
rb_sys_fail(0);
|
||
|
}
|
||
| ... | ... | |
|
rb_ary_push(res, rp?rb_ary_new():rb_ary_new2(0));
|
||
|
rb_ary_push(res, wp?rb_ary_new():rb_ary_new2(0));
|
||
|
rb_ary_push(res, ep?rb_ary_new():rb_ary_new2(0));
|
||
|
rb_ary_push(res, erp?rb_ary_new():rb_ary_new2(0));
|
||
|
if (!select_iface)
|
||
|
rb_ary_push(res, erp?rb_ary_new():rb_ary_new2(0));
|
||
|
if (rp) {
|
||
|
list = RARRAY_AREF(res, 0);
|
||
| ... | ... | |
|
struct select_args {
|
||
|
VALUE read, write, except, error;
|
||
|
struct timeval *timeout;
|
||
|
bool select_iface;
|
||
|
rb_fdset_t fdsets[5];
|
||
|
};
|
||
| ... | ... | |
|
{
|
||
|
struct select_args *p = (struct select_args *)arg;
|
||
|
return select_internal(p->read, p->write, p->except, p->error, p->timeout, p->fdsets);
|
||
|
return select_internal(p->read, p->write, p->except, p->error, p->timeout, p->select_iface, p->fdsets);
|
||
|
}
|
||
|
static VALUE
|
||
| ... | ... | |
|
*
|
||
|
* On systems that support poll(2) system call IO.select_with_poll is provided
|
||
|
* which takes and returns extra array of descriptors. Descriptors in this
|
||
|
* extra array and all other arrays are checked for error conditions -
|
||
|
* typically the other side closing the pipe or socket.
|
||
|
* extra array are checked for error conditions - typically the other side
|
||
|
* closing the pipe or socket. Descriptors returned in fourth array instead of
|
||
|
* raising Errno::EBADF.
|
||
|
*
|
||
|
* IO.select peeks the buffer of IO objects for testing readability.
|
||
|
* If the IO buffer is not empty, IO.select immediately notifies
|
||
| ... | ... | |
|
struct select_args args;
|
||
|
rb_scan_args(argc, argv, "14", &args.read, &args.write, &args.except, &args.error, &timeout);
|
||
|
args.select_iface = false;
|
||
|
return do_rb_f_select(&args, timeout);
|
||
|
}
|
||
|
#endif
|
||
|
static VALUE
|
||
|
rb_f_select(int argc, VALUE *argv, VALUE obj)
|
||
|
{
|
||
|
VALUE timeout, rv;
|
||
|
VALUE timeout;
|
||
|
struct select_args args;
|
||
|
rb_scan_args(argc, argv, "13", &args.read, &args.write, &args.except, &timeout);
|
||
|
args.error = Qnil;
|
||
|
rv = do_rb_f_select(&args, timeout);
|
||
|
if (RB_TYPE_P(rv, T_ARRAY))
|
||
|
rb_ary_pop(rv);
|
||
|
return rv;
|
||
|
args.select_iface = true;
|
||
|
return do_rb_f_select(&args, timeout);
|
||
|
}
|
||
|
static VALUE
|
||
| thread.c | ||
|---|---|---|
|
rb_fd_zero(fds);
|
||
|
for (i = 0; i < pollfdset->n_fds; i++)
|
||
|
if (pollfdset->fds[i].revents & (flags | POLLERR_SET))
|
||
|
if (pollfdset->fds[i].revents & flags)
|
||
|
rb_fd_set(pollfdset->fds[i].fd, fds);
|
||
|
}
|
||
| ... | ... | |
|
}
|
||
|
int
|
||
|
rb_fd_select(int n, rb_fdset_t *readfds, rb_fdset_t *writefds, rb_fdset_t *exceptfds, rb_fdset_t *errorfds, struct timeval *timeout)
|
||
|
rb_fd_select(int n, rb_fdset_t *readfds, rb_fdset_t *writefds, rb_fdset_t *exceptfds, rb_fdset_t *errorfds,
|
||
|
struct timeval *timeout, bool select_iface)
|
||
|
{
|
||
|
struct rb_pollfdset pollfdset;
|
||
|
int timeout_ms = timeout ? timeout->tv_sec * 1000 + timeout->tv_usec / 1000 : -1;
|
||
|
bool badfd;
|
||
|
bool badfd = false;
|
||
|
int ret;
|
||
|
pollfdset_init(&pollfdset);
|
||
| ... | ... | |
|
if (exceptfds) pollfdset_add(&pollfdset, exceptfds, POLLEX_SET);
|
||
|
if (errorfds) pollfdset_add(&pollfdset, errorfds, POLLERR_SET);
|
||
|
ret = poll(pollfdset.fds, pollfdset.n_fds, timeout_ms);
|
||
|
badfd = pollfdset_badfd(&pollfdset);
|
||
|
if (select_iface)
|
||
|
badfd = pollfdset_badfd(&pollfdset);
|
||
|
if (badfd) {
|
||
|
if (readfds) rb_fd_zero(readfds);
|
||
|
if (writefds) rb_fd_zero(writefds);
|
||
|
if (exceptfds) rb_fd_zero(exceptfds);
|
||
|
if (errorfds) rb_fd_zero(errorfds);
|
||
|
} else {
|
||
|
if (readfds) pollfdset_extract(&pollfdset, readfds, POLLIN_SET);
|
||
|
if (readfds) pollfdset_extract(&pollfdset, readfds, POLLIN_SET |
|
||
|
(select_iface ? POLLERR_SET : 0));
|
||
|
if (writefds) pollfdset_extract(&pollfdset, writefds, POLLOUT_SET);
|
||
|
if (exceptfds) pollfdset_extract(&pollfdset, exceptfds, POLLEX_SET);
|
||
|
if (errorfds) pollfdset_extract(&pollfdset, errorfds, POLLERR_SET);
|
||
| ... | ... | |
|
rb_fdset_t orig_eset;
|
||
|
rb_fdset_t orig_errset;
|
||
|
struct timeval *timeout;
|
||
|
_Bool select_iface;
|
||
|
};
|
||
|
static VALUE
|
||
| ... | ... | |
|
if (!RUBY_VM_INTERRUPTED(set->th->ec)) {
|
||
|
result = native_fd_select(set->max, set->rset, set->wset,
|
||
|
set->eset, set->errset,
|
||
|
rb_hrtime2timeval(&tv, sto), set->th);
|
||
|
rb_hrtime2timeval(&tv, sto),
|
||
|
set->select_iface, set->th);
|
||
|
if (result < 0) lerrno = errno;
|
||
|
}
|
||
|
}, set->sigwait_fd >= 0 ? ubf_sigwait : ubf_select, set->th, TRUE);
|
||
| ... | ... | |
|
int
|
||
|
rb_thread_fd_select(int max, rb_fdset_t * read, rb_fdset_t * write, rb_fdset_t * except,
|
||
|
rb_fdset_t * error, struct timeval *timeout)
|
||
|
rb_fdset_t * error, struct timeval *timeout, _Bool select_iface)
|
||
|
{
|
||
|
struct select_set set;
|
||
| ... | ... | |
|
set.eset = except;
|
||
|
set.errset = error;
|
||
|
set.timeout = timeout;
|
||
|
set.select_iface = select_iface;
|
||
|
if (!set.rset && !set.wset && !set.eset && !set.errset) {
|
||
|
if (!timeout) {
|
||
| thread_pthread.c | ||
|---|---|---|
|
#endif /* USE_NATIVE_THREAD_PRIORITY */
|
||
|
static int
|
||
|
native_fd_select(int n, rb_fdset_t *readfds, rb_fdset_t *writefds, rb_fdset_t *exceptfds, rb_fdset_t *errorfds, struct timeval *timeout, rb_thread_t *th)
|
||
|
native_fd_select(int n, rb_fdset_t *readfds, rb_fdset_t *writefds, rb_fdset_t *exceptfds, rb_fdset_t *errorfds, struct timeval *timeout, _Bool select_iface, rb_thread_t *th)
|
||
|
{
|
||
|
return rb_fd_select(n, readfds, writefds, exceptfds, errorfds, timeout);
|
||
|
return rb_fd_select(n, readfds, writefds, exceptfds, errorfds, timeout, select_iface);
|
||
|
}
|
||
|
static void
|
||
| thread_win32.c | ||
|---|---|---|
|
int rb_w32_select_with_thread(int, fd_set *, fd_set *, fd_set *, struct timeval *, void *); /* @internal */
|
||
|
static int
|
||
|
native_fd_select(int n, rb_fdset_t *readfds, rb_fdset_t *writefds, rb_fdset_t *exceptfds, struct timeval *timeout, rb_thread_t *th)
|
||
|
native_fd_select(int n, rb_fdset_t *readfds, rb_fdset_t *writefds, rb_fdset_t *exceptfds,
|
||
|
struct timeval *timeout, _Bool select_iface, rb_thread_t *th)
|
||
|
{
|
||
|
fd_set *r = NULL, *w = NULL, *e = NULL;
|
||
|
if (readfds) {
|
||