Skip to content

Commit

Permalink
Fix incorrect usage of rb_fiber_scheduler_io_(p)(read|write). (#7593)
Browse files Browse the repository at this point in the history
  • Loading branch information
ioquatix committed Mar 25, 2023
1 parent 276f4be commit 466aa80
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 28 deletions.
8 changes: 4 additions & 4 deletions io_buffer.c
Expand Up @@ -2430,7 +2430,7 @@ rb_io_buffer_read(VALUE self, VALUE io, size_t length, size_t offset)
{
VALUE scheduler = rb_fiber_scheduler_current();
if (scheduler != Qnil) {
VALUE result = rb_fiber_scheduler_io_read(scheduler, io, self, SIZET2NUM(length), SIZET2NUM(offset));
VALUE result = rb_fiber_scheduler_io_read(scheduler, io, self, length, offset);

if (!UNDEF_P(result)) {
return result;
Expand Down Expand Up @@ -2544,7 +2544,7 @@ rb_io_buffer_pread(VALUE self, VALUE io, rb_off_t from, size_t length, size_t of
{
VALUE scheduler = rb_fiber_scheduler_current();
if (scheduler != Qnil) {
VALUE result = rb_fiber_scheduler_io_pread(scheduler, io, OFFT2NUM(from), self, SIZET2NUM(length), SIZET2NUM(offset));
VALUE result = rb_fiber_scheduler_io_pread(scheduler, io, from, self, length, offset);

if (!UNDEF_P(result)) {
return result;
Expand Down Expand Up @@ -2649,7 +2649,7 @@ rb_io_buffer_write(VALUE self, VALUE io, size_t length, size_t offset)
{
VALUE scheduler = rb_fiber_scheduler_current();
if (scheduler != Qnil) {
VALUE result = rb_fiber_scheduler_io_write(scheduler, io, self, SIZET2NUM(length), SIZET2NUM(offset));
VALUE result = rb_fiber_scheduler_io_write(scheduler, io, self, length, offset);

if (!UNDEF_P(result)) {
return result;
Expand Down Expand Up @@ -2753,7 +2753,7 @@ rb_io_buffer_pwrite(VALUE self, VALUE io, rb_off_t from, size_t length, size_t o
{
VALUE scheduler = rb_fiber_scheduler_current();
if (scheduler != Qnil) {
VALUE result = rb_fiber_scheduler_io_pwrite(scheduler, io, OFFT2NUM(from), self, SIZET2NUM(length), SIZET2NUM(offset));
VALUE result = rb_fiber_scheduler_io_pwrite(scheduler, io, from, self, length, offset);

if (!UNDEF_P(result)) {
return result;
Expand Down
48 changes: 24 additions & 24 deletions scheduler.c
Expand Up @@ -458,28 +458,27 @@ VALUE rb_fiber_scheduler_io_selectv(VALUE scheduler, int argc, VALUE *argv)

/*
* Document-method: Fiber::Scheduler#io_read
* call-seq: io_read(io, buffer, length) -> read length or -errno
* call-seq: io_read(io, buffer, minimum_length) -> read length or -errno
*
* Invoked by IO#read to read +length+ bytes from +io+ into a specified
* +buffer+ (see IO::Buffer).
* Invoked by IO#read or IO#Buffer.read to read +length+ bytes from +io+ into a
* specified +buffer+ (see IO::Buffer).
*
* The +length+ argument is the "minimum length to be read".
* If the IO buffer size is 8KiB, but the +length+ is +1024+ (1KiB), up to
* 8KiB might be read, but at least 1KiB will be.
* Generally, the only case where less data than +length+ will be read is if
* there is an error reading the data.
* The +minimum_length+ argument is the "minimum length to be read". If the IO
* buffer size is 8KiB, but the +length+ is +1024+ (1KiB), up to 8KiB might be
* read, but at least 1KiB will be. Generally, the only case where less data
* than +length+ will be read is if there is an error reading the data.
*
* Specifying a +length+ of 0 is valid and means try reading at least once
* and return any available data.
* Specifying a +length+ of 0 is valid and means try reading at least once and
* return any available data.
*
* Suggested implementation should try to read from +io+ in a non-blocking
* manner and call #io_wait if the +io+ is not ready (which will yield control
* to other fibers).
*
* See IO::Buffer for an interface available to return data.
*
* Expected to return number of bytes read, or, in case of an error, <tt>-errno</tt>
* (negated number corresponding to system's error code).
* Expected to return number of bytes read, or, in case of an error,
* <tt>-errno</tt> (negated number corresponding to system's error code).
*
* The method should be considered _experimental_.
*/
Expand Down Expand Up @@ -513,28 +512,29 @@ rb_fiber_scheduler_io_pread(VALUE scheduler, VALUE io, rb_off_t from, VALUE buff

/*
* Document-method: Scheduler#io_write
* call-seq: io_write(io, buffer, length) -> written length or -errno
* call-seq: io_write(io, buffer, minimum_length) -> written length or -errno
*
* Invoked by IO#write to write +length+ bytes to +io+ from
* Invoked by IO#write or IO::Buffer#write to write +length+ bytes to +io+ from
* from a specified +buffer+ (see IO::Buffer).
*
* The +length+ argument is the "(minimum) length to be written".
* If the IO buffer size is 8KiB, but the +length+ specified is 1024 (1KiB),
* at most 8KiB will be written, but at least 1KiB will be.
* Generally, the only case where less data than +length+ will be written is if
* there is an error writing the data.
* The +minimum_length+ argument is the "minimum length to be written". If the
* IO buffer size is 8KiB, but the +length+ specified is 1024 (1KiB), at most
* 8KiB will be written, but at least 1KiB will be. Generally, the only case
* where less data than +minimum_length+ will be written is if there is an
* error writing the data.
*
* Specifying a +length+ of 0 is valid and means try writing at least once,
* as much data as possible.
* Specifying a +length+ of 0 is valid and means try writing at least once, as
* much data as possible.
*
* Suggested implementation should try to write to +io+ in a non-blocking
* manner and call #io_wait if the +io+ is not ready (which will yield control
* to other fibers).
*
* See IO::Buffer for an interface available to get data from buffer efficiently.
* See IO::Buffer for an interface available to get data from buffer
* efficiently.
*
* Expected to return number of bytes written, or, in case of an error, <tt>-errno</tt>
* (negated number corresponding to system's error code).
* Expected to return number of bytes written, or, in case of an error,
* <tt>-errno</tt> (negated number corresponding to system's error code).
*
* The method should be considered _experimental_.
*/
Expand Down
33 changes: 33 additions & 0 deletions test/fiber/test_io_buffer.rb
Expand Up @@ -122,4 +122,37 @@ def test_write_nonblock
i&.close
o&.close
end

def test_io_buffer_read_write
omit "UNIXSocket is not defined!" unless defined?(UNIXSocket)

i, o = UNIXSocket.pair
source_buffer = IO::Buffer.for("Hello World!")
destination_buffer = IO::Buffer.new(source_buffer.size)

# Test non-scheduler code path:
source_buffer.write(o, source_buffer.size)
destination_buffer.read(i, source_buffer.size)
assert_equal source_buffer, destination_buffer

# Test scheduler code path:
destination_buffer.clear

thread = Thread.new do
scheduler = IOBufferScheduler.new
Fiber.set_scheduler scheduler

Fiber.schedule do
source_buffer.write(o, source_buffer.size)
destination_buffer.read(i, source_buffer.size)
end
end

thread.join

assert_equal source_buffer, destination_buffer
ensure
i&.close
o&.close
end
end

0 comments on commit 466aa80

Please sign in to comment.