Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion ext/io/event/selector/uring.c
Original file line number Diff line number Diff line change
Expand Up @@ -707,6 +707,20 @@ VALUE IO_Event_Selector_URing_io_read(VALUE self, VALUE fiber, VALUE io, VALUE b
off_t from = io_seekable(descriptor);

size_t maximum_size = size - offset;

// Are we performing a non-blocking read?
if (!length) {
// If the (maximum) length is zero, that indicates we just want to read whatever is available without blocking.
// If we schedule this read into the URing, it will block until data is available, rather than returning immediately.
int state = IO_Event_Selector_nonblock_set(descriptor);

int result = read(descriptor, (char*)base+offset, maximum_size);
int error = errno;

IO_Event_Selector_nonblock_restore(descriptor, state);
return rb_fiber_scheduler_io_result(result, errno);
}

while (maximum_size) {
int result = io_read(selector, fiber, descriptor, (char*)base+offset, maximum_size, from);

Expand Down Expand Up @@ -1093,7 +1107,7 @@ unsigned select_process_completions(struct IO_Event_Selector_URing *selector) {
}
}

if (DEBUG && completed > 0) fprintf(stderr, "select_process_completions(completed=%d)\n", completed);
if (DEBUG && completed > 0) fprintf(stderr, "select_process_completions: completed=%d\n", completed);

return completed;
}
Expand Down
40 changes: 40 additions & 0 deletions test/io/event/selector/buffered_io.rb
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,46 @@
writer.transfer
selector.select(0)
end

it "can perform non-blocking read" do
skip_if_ruby_platform(/mswin|mingw|cygwin/)

buffer = IO::Buffer.new(64)
result = nil

output.puts "Hello World\n"
output.close

reader = Fiber.new do
result = selector.io_read(Fiber.current, input, buffer, 0)
end

reader.transfer
selector.select(0)

expect(buffer.get_string(0, 12)).to be == "Hello World\n"
end

# Whether the given error code indicates that the operation should be retried.
def be_again?
(be == -Errno::EAGAIN::Errno).or(be == -Errno::EWOULDBLOCK::Errno)
end

it "can perform non-blocking read with empty input" do
skip_if_ruby_platform(/mswin|mingw|cygwin/)

buffer = IO::Buffer.new(64)
result = nil

reader = Fiber.new do
result = selector.io_read(Fiber.current, input, buffer, 0)
end

reader.transfer
selector.select(0)

expect(result).to be_again?
end
end
end

Expand Down
Loading