fix rb_thread_wait_for_single_fd on non MN case

`rb_thread_wait_for_single_fd(fd)` waits until `fd` is ready.
Without MN it shouldn't use `thread_io_wait_events()` for the
retry checking (alwasy false if MN is not active).
This commit is contained in:
Koichi Sasada 2024-01-09 00:27:40 +09:00
parent 47ff4a1658
commit 41dd15944f

View File

@ -4342,7 +4342,11 @@ rb_thread_fd_select(int max, rb_fdset_t * read, rb_fdset_t * write, rb_fdset_t *
int int
rb_thread_wait_for_single_fd(int fd, int events, struct timeval *timeout) rb_thread_wait_for_single_fd(int fd, int events, struct timeval *timeout)
{ {
struct pollfd fds[1]; struct pollfd fds[1] = {{
.fd = fd,
.events = (short)events,
.revents = 0,
}};
int result = 0; int result = 0;
nfds_t nfds; nfds_t nfds;
struct waiting_fd wfd; struct waiting_fd wfd;
@ -4354,37 +4358,36 @@ rb_thread_wait_for_single_fd(int fd, int events, struct timeval *timeout)
thread_io_setup_wfd(th, fd, &wfd); thread_io_setup_wfd(th, fd, &wfd);
EC_PUSH_TAG(wfd.th->ec); if (timeout == NULL && thread_io_wait_events(th, fd, events, NULL)) {
if ((state = EC_EXEC_TAG()) == TAG_NONE) { // fd is readable
rb_hrtime_t *to, rel, end = 0; state = 0;
struct timeval tv; fds[0].revents = events;
errno = 0;
RUBY_VM_CHECK_INTS_BLOCKING(wfd.th->ec); }
else {
timeout_prepare(&to, &rel, &end, timeout); EC_PUSH_TAG(wfd.th->ec);
fds[0].fd = fd; if ((state = EC_EXEC_TAG()) == TAG_NONE) {
fds[0].events = (short)events; rb_hrtime_t *to, rel, end = 0;
fds[0].revents = 0; RUBY_VM_CHECK_INTS_BLOCKING(wfd.th->ec);
timeout_prepare(&to, &rel, &end, timeout);
do { do {
nfds = 1; nfds = 1;
lerrno = 0; lerrno = 0;
BLOCKING_REGION(wfd.th, { BLOCKING_REGION(wfd.th, {
struct timespec ts; struct timespec ts;
if (!RUBY_VM_INTERRUPTED(wfd.th->ec)) { if (!RUBY_VM_INTERRUPTED(wfd.th->ec)) {
result = ppoll(fds, nfds, rb_hrtime2timespec(&ts, to), 0); result = ppoll(fds, nfds, rb_hrtime2timespec(&ts, to), 0);
if (result < 0) lerrno = errno; if (result < 0) lerrno = errno;
} }
}, ubf_select, wfd.th, TRUE); }, ubf_select, wfd.th, TRUE);
RUBY_VM_CHECK_INTS_BLOCKING(wfd.th->ec); RUBY_VM_CHECK_INTS_BLOCKING(wfd.th->ec);
} while (wait_retryable(&result, lerrno, to, end) && } while (wait_retryable(&result, lerrno, to, end));
thread_io_wait_events(th, fd, events, rb_hrtime2timeval(&tv, to)) && }
wait_retryable(&result, lerrno, to, end)); EC_POP_TAG();
} }
EC_POP_TAG();
thread_io_wake_pending_closer(&wfd); thread_io_wake_pending_closer(&wfd);