summaryrefslogtreecommitdiff
path: root/io.c
diff options
context:
space:
mode:
authornormal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-11-22 08:46:51 +0000
committernormal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-11-22 08:46:51 +0000
commit6a65f2b1e479f268489b51a004b6c153c634c68a (patch)
tree5e7bae4d2418fd88b152380075eb6a1f21f2401b /io.c
parentb009de13bf4bb7c96964c404fb56b3503db777fd (diff)
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
Diffstat (limited to 'io.c')
-rw-r--r--io.c45
1 files changed, 25 insertions, 20 deletions
diff --git a/io.c b/io.c
index 9e0b1b9844..0fe0d7a4b2 100644
--- a/io.c
+++ b/io.c
@@ -316,6 +316,27 @@ rb_cloexec_dup2(int oldfd, int newfd)
return ret;
}
+static int
+rb_fd_set_nonblock(int fd)
+{
+#ifdef _WIN32
+ return rb_w32_set_nonblock(fd);
+#elif defined(F_GETFL)
+ int err;
+ int oflags = fcntl(fd, F_GETFL);
+
+ if (oflags == -1)
+ return -1;
+ if (oflags & O_NONBLOCK)
+ return 0;
+ oflags |= O_NONBLOCK;
+ err = fcntl(fd, F_SETFL, oflags);
+ if (err == -1)
+ return -1;
+#endif
+ return 0;
+}
+
int
rb_cloexec_pipe(int fildes[2])
{
@@ -324,7 +345,7 @@ rb_cloexec_pipe(int fildes[2])
#if defined(HAVE_PIPE2)
static int try_pipe2 = 1;
if (try_pipe2) {
- ret = pipe2(fildes, O_CLOEXEC);
+ ret = pipe2(fildes, O_CLOEXEC | O_NONBLOCK);
if (ret != -1)
return ret;
/* pipe2 is available since Linux 2.6.27, glibc 2.9. */
@@ -350,6 +371,8 @@ rb_cloexec_pipe(int fildes[2])
#endif
rb_maygvl_fd_fix_cloexec(fildes[0]);
rb_maygvl_fd_fix_cloexec(fildes[1]);
+ rb_fd_set_nonblock(fildes[0]);
+ rb_fd_set_nonblock(fildes[1]);
return ret;
}
@@ -2696,27 +2719,9 @@ read_all(rb_io_t *fptr, long siz, VALUE str)
void
rb_io_set_nonblock(rb_io_t *fptr)
{
-#ifdef _WIN32
- if (rb_w32_set_nonblock(fptr->fd) != 0) {
+ if (rb_fd_set_nonblock(fptr->fd) != 0) {
rb_sys_fail_path(fptr->pathv);
}
-#else
- int oflags;
-#ifdef F_GETFL
- oflags = fcntl(fptr->fd, F_GETFL);
- if (oflags == -1) {
- rb_sys_fail_path(fptr->pathv);
- }
-#else
- oflags = 0;
-#endif
- if ((oflags & O_NONBLOCK) == 0) {
- oflags |= O_NONBLOCK;
- if (fcntl(fptr->fd, F_SETFL, oflags) == -1) {
- rb_sys_fail_path(fptr->pathv);
- }
- }
-#endif
}
struct read_internal_arg {