зеркало из https://github.com/github/ruby.git
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(-)
This commit is contained in:
Родитель
c13757ed9a
Коммит
5ad2390b55
|
@ -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;
|
||||
|
|
48
scheduler.c
48
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, <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_.
|
||||
*/
|
||||
|
@ -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_.
|
||||
*/
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
Загрузка…
Ссылка в новой задаче