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
Родитель 47ff4a1658
Коммит 41dd15944f
1 изменённых файлов: 34 добавлений и 31 удалений

Просмотреть файл

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