From 2108ab2cb68e9d975e4dcf035a11243e1173336f Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Thu, 13 Feb 2025 21:09:15 -0800 Subject: [PATCH] merge revision(s) 04ec07794657cd2444ecb001a522b9df2db1b90a: [Backport #21038] Preserve `errno` in `rb_fiber_scheduler_unblock`. (#12576) [Bug #21038] Co-authored-by: Julian Scheid --- scheduler.c | 10 +++++++++- version.h | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/scheduler.c b/scheduler.c index bb406a5cf6..edb38b666c 100644 --- a/scheduler.c +++ b/scheduler.c @@ -412,7 +412,15 @@ rb_fiber_scheduler_unblock(VALUE scheduler, VALUE blocker, VALUE fiber) { RUBY_ASSERT(rb_obj_is_fiber(fiber)); - return rb_funcall(scheduler, id_unblock, 2, blocker, fiber); + // `rb_fiber_scheduler_unblock` can be called from points where `errno` is expected to be preserved. Therefore, we should save and restore it. For example `io_binwrite` calls `rb_fiber_scheduler_unblock` and if `errno` is reset to 0 by user code, it will break the error handling in `io_write`. + // If we explicitly preserve `errno` in `io_binwrite` and other similar functions (e.g. by returning it), this code is no longer needed. I hope in the future we will be able to remove it. + int saved_errno = errno; + + VALUE result = rb_funcall(scheduler, id_unblock, 2, blocker, fiber); + + errno = saved_errno; + + return result; } /* diff --git a/version.h b/version.h index 6267bdc70f..ce08b11d47 100644 --- a/version.h +++ b/version.h @@ -11,7 +11,7 @@ # define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR #define RUBY_VERSION_TEENY 1 #define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR -#define RUBY_PATCHLEVEL 18 +#define RUBY_PATCHLEVEL 19 #include "ruby/version.h" #include "ruby/internal/abi.h"