From 5ad2390b551f4a28ea3d4db78c21863489fdd681 Mon Sep 17 00:00:00 2001 From: nagachika Date: Sun, 16 Jul 2023 16:44:22 +0900 Subject: [PATCH] merge revision(s) 466aa8010fb49f9ec6c78ea1de4e8ca0965f4fdf: [Backport #19546] Fix incorrect usage of `rb_fiber_scheduler_io_(p)(read|write)`. (#7593) --- io_buffer.c | 8 ++++---- scheduler.c | 48 ++++++++++++++++++++++---------------------- test/fiber/test_io_buffer.rb | 33 ++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 28 deletions(-) --- io_buffer.c | 8 +++--- scheduler.c | 48 ++++++++++++++++++------------------ test/fiber/test_io_buffer.rb | 33 +++++++++++++++++++++++++ version.h | 2 +- 4 files changed, 62 insertions(+), 29 deletions(-) diff --git a/io_buffer.c b/io_buffer.c index 1fa6473328..115e5e7a58 100644 --- a/io_buffer.c +++ b/io_buffer.c @@ -2390,7 +2390,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; @@ -2504,7 +2504,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; @@ -2609,7 +2609,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; @@ -2713,7 +2713,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; diff --git a/scheduler.c b/scheduler.c index fb84e6b4dd..477f11c03c 100644 --- a/scheduler.c +++ b/scheduler.c @@ -458,19 +458,18 @@ 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 @@ -478,8 +477,8 @@ VALUE rb_fiber_scheduler_io_selectv(VALUE scheduler, int argc, VALUE *argv) * * See IO::Buffer for an interface available to return data. * - * Expected to return number of bytes read, or, in case of an error, -errno - * (negated number corresponding to system's error code). + * Expected to return number of bytes read, or, in case of an error, + * -errno (negated number corresponding to system's error code). * * The method should be considered _experimental_. */ @@ -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, -errno - * (negated number corresponding to system's error code). + * Expected to return number of bytes written, or, in case of an error, + * -errno (negated number corresponding to system's error code). * * The method should be considered _experimental_. */ diff --git a/test/fiber/test_io_buffer.rb b/test/fiber/test_io_buffer.rb index 48a34c31b6..3de70200d5 100644 --- a/test/fiber/test_io_buffer.rb +++ b/test/fiber/test_io_buffer.rb @@ -122,4 +122,37 @@ class TestFiberIOBuffer < Test::Unit::TestCase 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 diff --git a/version.h b/version.h index 639f98d7c4..26e5932c1c 100644 --- a/version.h +++ b/version.h @@ -11,7 +11,7 @@ # define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR #define RUBY_VERSION_TEENY 2 #define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR -#define RUBY_PATCHLEVEL 69 +#define RUBY_PATCHLEVEL 70 #include "ruby/version.h" #include "ruby/internal/abi.h"