mirror of
https://github.com/ruby/ruby.git
synced 2025-08-15 13:39:04 +02:00
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
This commit is contained in:
parent
b009de13bf
commit
6a65f2b1e4
14 changed files with 139 additions and 46 deletions
44
process.c
44
process.c
|
@ -1474,6 +1474,39 @@ before_exec_non_async_signal_safe(void)
|
|||
rb_thread_stop_timer_thread();
|
||||
}
|
||||
|
||||
#define WRITE_CONST(fd, str) (void)(write((fd),(str),sizeof(str)-1)<0)
|
||||
#ifdef _WIN32
|
||||
int rb_w32_set_nonblock2(int fd, int nonblock);
|
||||
#endif
|
||||
|
||||
static int
|
||||
set_blocking(int fd)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return rb_w32_set_nonblock2(fd, 0);
|
||||
#elif defined(F_GETFL) && defined(F_SETFL)
|
||||
int fl = fcntl(fd, F_GETFL); /* async-signal-safe */
|
||||
|
||||
/* EBADF ought to be possible */
|
||||
if (fl == -1) return fl;
|
||||
if (fl & O_NONBLOCK) {
|
||||
fl &= ~O_NONBLOCK;
|
||||
return fcntl(fd, F_SETFL, fl);
|
||||
}
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
stdfd_clear_nonblock(void)
|
||||
{
|
||||
/* many programs cannot deal with non-blocking stdin/stdout/stderr */
|
||||
int fd;
|
||||
for (fd = 0; fd < 3; fd++) {
|
||||
(void)set_blocking(fd); /* can't do much about errors anyhow */
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
before_exec(void)
|
||||
{
|
||||
|
@ -3445,6 +3478,11 @@ rb_execarg_run_options(const struct rb_execarg *eargp, struct rb_execarg *sargp,
|
|||
rb_execarg_allocate_dup2_tmpbuf(sargp, RARRAY_LEN(ary));
|
||||
}
|
||||
}
|
||||
{
|
||||
int preserve = errno;
|
||||
stdfd_clear_nonblock();
|
||||
errno = preserve;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -3645,6 +3683,12 @@ read_retry(int fd, void *buf, size_t len)
|
|||
{
|
||||
ssize_t r;
|
||||
|
||||
if (set_blocking(fd) != 0) {
|
||||
#ifndef _WIN32
|
||||
rb_async_bug_errno("set_blocking failed reading child error", errno);
|
||||
#endif
|
||||
}
|
||||
|
||||
do {
|
||||
r = read(fd, buf, len);
|
||||
} while (r < 0 && errno == EINTR);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue