From 6a65f2b1e479f268489b51a004b6c153c634c68a Mon Sep 17 00:00:00 2001 From: normal Date: Thu, 22 Nov 2018 08:46:51 +0000 Subject: io + socket: make pipes and sockets nonblocking by default All normal Ruby IO methods (IO#read, IO#gets, IO#write, ...) are all capable of appearing to be "blocking" when presented with a file description with the O_NONBLOCK flag set; so there is little risk of incompatibility within Ruby-using programs. The biggest compatibility risk is when spawning external programs. As a result, stdin, stdout, and stderr are now always made blocking before exec-family calls. This change will make an event-oriented MJIT usable if it is waiting on pipes on POSIX_like platforms. It is ALSO necessary to take advantage of (proposed lightweight concurrency (aka "auto-Fiber") or any similar proposal for network concurrency: https://bugs.ruby-lang.org/issues/13618 Named-pipe (FIFO) are NOT yet non-blocking by default since they are rarely-used and may introduce compatibility problems and extra syscall overhead for a common path. Please revert this commit if there are problems and if I am afk since I am afk a lot, lately. [ruby-core:89950] [Bug #14968] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@65922 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- thread.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) (limited to 'thread.c') diff --git a/thread.c b/thread.c index 95fbcda203..7790bad002 100644 --- a/thread.c +++ b/thread.c @@ -4068,17 +4068,19 @@ rb_wait_for_single_fd(int fd, int events, struct timeval *timeout) int result = 0, lerrno; rb_hrtime_t *to, rel, end = 0; int drained; - rb_thread_t *th = GET_THREAD(); nfds_t nfds; rb_unblock_function_t *ubf; + struct waiting_fd wfd; - RUBY_VM_CHECK_INTS_BLOCKING(th->ec); + wfd.th = GET_THREAD(); + wfd.fd = fd; + RUBY_VM_CHECK_INTS_BLOCKING(wfd.th->ec); timeout_prepare(&to, &rel, &end, timeout); fds[0].fd = fd; fds[0].events = (short)events; do { fds[0].revents = 0; - fds[1].fd = rb_sigwait_fd_get(th); + fds[1].fd = rb_sigwait_fd_get(wfd.th); if (fds[1].fd >= 0) { fds[1].events = POLLIN; @@ -4092,27 +4094,29 @@ rb_wait_for_single_fd(int fd, int events, struct timeval *timeout) } lerrno = 0; - BLOCKING_REGION(th, { + list_add(&wfd.th->vm->waiting_fds, &wfd.wfd_node); + BLOCKING_REGION(wfd.th, { const rb_hrtime_t *sto; struct timespec ts; - sto = sigwait_timeout(th, fds[1].fd, to, &drained); - if (!RUBY_VM_INTERRUPTED(th->ec)) { + sto = sigwait_timeout(wfd.th, fds[1].fd, to, &drained); + if (!RUBY_VM_INTERRUPTED(wfd.th->ec)) { result = ppoll(fds, nfds, rb_hrtime2timespec(&ts, sto), NULL); if (result < 0) lerrno = errno; } - }, ubf, th, TRUE); + }, ubf, wfd.th, TRUE); + list_del(&wfd.wfd_node); if (fds[1].fd >= 0) { if (result > 0 && fds[1].revents) { result--; fds[1].revents = 0; } - (void)check_signals_nogvl(th, fds[1].fd); - rb_sigwait_fd_put(th, fds[1].fd); - rb_sigwait_fd_migrate(th->vm); + (void)check_signals_nogvl(wfd.th, fds[1].fd); + rb_sigwait_fd_put(wfd.th, fds[1].fd); + rb_sigwait_fd_migrate(wfd.th->vm); } - RUBY_VM_CHECK_INTS_BLOCKING(th->ec); + RUBY_VM_CHECK_INTS_BLOCKING(wfd.th->ec); } while (wait_retryable(&result, lerrno, to, end)); if (result < 0) { @@ -4152,6 +4156,7 @@ struct select_args { rb_fdset_t *read; rb_fdset_t *write; rb_fdset_t *except; + struct waiting_fd wfd; struct timeval *tv; }; @@ -4182,6 +4187,7 @@ select_single_cleanup(VALUE ptr) { struct select_args *args = (struct select_args *)ptr; + list_del(&args->wfd.wfd_node); if (args->read) rb_fd_term(args->read); if (args->write) rb_fd_term(args->write); if (args->except) rb_fd_term(args->except); @@ -4202,7 +4208,10 @@ rb_wait_for_single_fd(int fd, int events, struct timeval *tv) args.write = (events & RB_WAITFD_OUT) ? init_set_fd(fd, &wfds) : NULL; args.except = (events & RB_WAITFD_PRI) ? init_set_fd(fd, &efds) : NULL; args.tv = tv; + args.wfd.fd = fd; + args.wfd.th = GET_THREAD(); + list_add(&args.wfd.th->vm->waiting_fds, &args.wfd.wfd_node); r = (int)rb_ensure(select_single, ptr, select_single_cleanup, ptr); if (r == -1) errno = args.as.error; -- cgit v1.2.3