Project

General

Profile

Feature #11056 » io_wait_readable-no-nread-experimental.patch

normalperson (Eric Wong), 04/11/2015 07:47 AM

View differences:

ext/io/wait/wait.c
#define FIONREAD_POSSIBLE_P(fd) ((void)(fd),Qtrue)
#endif
static VALUE sym_wait_only;
static VALUE io_ready_p _((VALUE io));
static VALUE io_wait_readable _((int argc, VALUE *argv, VALUE io));
static VALUE io_wait_writable _((int argc, VALUE *argv, VALUE io));
......
io_wait_readable(int argc, VALUE *argv, VALUE io)
{
rb_io_t *fptr;
VALUE opts = Qnil;
int i;
ioctl_arg n;
VALUE timeout;
struct timeval timerec;
struct timeval *tv;
int check_nread = 1;
GetOpenFile(io, fptr);
rb_io_check_readable(fptr);
rb_scan_args(argc, argv, "01", &timeout);
rb_scan_args(argc, argv, "01:", &timeout, &opts);
if (!NIL_P(opts) && Qtrue == rb_hash_lookup2(opts, sym_wait_only, Qundef))
check_nread = 0;
if (NIL_P(timeout)) {
tv = NULL;
}
......
}
if (rb_io_read_pending(fptr)) return Qtrue;
if (!FIONREAD_POSSIBLE_P(fptr->fd)) return Qfalse;
if (check_nread && !FIONREAD_POSSIBLE_P(fptr->fd)) return Qfalse;
i = rb_wait_for_single_fd(fptr->fd, RB_WAITFD_IN, tv);
if (i < 0)
rb_sys_fail(0);
rb_io_check_closed(fptr);
if (ioctl(fptr->fd, FIONREAD, &n)) rb_sys_fail(0);
if (n > 0) return io;
if (check_nread) {
ioctl_arg n;
if (ioctl(fptr->fd, FIONREAD, &n)) rb_sys_fail(0);
if (n > 0) return io;
} else {
if (i & RB_WAITFD_IN)
return io;
}
return Qnil;
}
......
rb_define_method(rb_cIO, "wait", io_wait_readable, -1);
rb_define_method(rb_cIO, "wait_readable", io_wait_readable, -1);
rb_define_method(rb_cIO, "wait_writable", io_wait_writable, -1);
sym_wait_only = ID2SYM(rb_intern("wait_only"));
}
lib/net/http/generic_request.rb
def wait_for_continue(sock, ver)
if ver >= '1.1' and @header['expect'] and
@header['expect'].include?('100-continue')
if IO.select([sock.io], nil, nil, sock.continue_timeout)
if sock.io.to_io.wait_readable(sock.continue_timeout, wait_only: true)
res = Net::HTTPResponse.read_new(sock)
unless res.kind_of?(Net::HTTPContinue)
res.decode_content = @decode_content
lib/net/protocol.rb
require 'socket'
require 'timeout'
require 'io/wait'
module Net # :nodoc:
......
when String
return @rbuf << rv
when :wait_readable
IO.select([@io], nil, nil, @read_timeout) or raise Net::ReadTimeout
@io.to_io.wait_readable(@read_timeout, wait_only: true) or
raise Net::ReadTimeout
# continue looping
when :wait_writable
# OpenSSL::Buffering#read_nonblock may fail with IO::WaitWritable.
# http://www.openssl.org/support/faq.html#PROG10
IO.select(nil, [@io], nil, @read_timeout) or raise Net::ReadTimeout
@io.to_io.wait_writable(@read_timeout) or raise Net::ReadTimeout
# continue looping
when nil
# callers do not care about backtrace, so avoid allocating for it
test/io/wait/test_io_wait.rb
assert_raises(IOError) { @w.wait_writable }
end
def test_wait_readable_wait_only
host = '127.0.0.1'
s = TCPServer.new(host, 0)
assert_nil s.wait_readable(0.01, wait_only: true)
c = TCPSocket.new(host, s.addr[1])
assert_equal s, s.wait_readable(wait_only: true)
ensure
s.close if s
c.close if c
end
private
def fill_pipe
-
(2-2/2)