summaryrefslogtreecommitdiff
path: root/scheduler.c
diff options
context:
space:
mode:
authorSamuel Williams <[email protected]>2025-01-15 14:59:46 +1300
committerGitHub <[email protected]>2025-01-15 14:59:46 +1300
commit04ec07794657cd2444ecb001a522b9df2db1b90a (patch)
tree7907cda025fdb3817dc420cd57a782b66b5481c3 /scheduler.c
parentcb419e3912f0514b8151469b0a4a4b83cbbcce78 (diff)
Preserve `errno` in `rb_fiber_scheduler_unblock`. (#12576)
[Bug #21038] Co-authored-by: Julian Scheid <[email protected]>
Notes
Notes: Merged-By: ioquatix <[email protected]>
Diffstat (limited to 'scheduler.c')
-rw-r--r--scheduler.c10
1 files changed, 9 insertions, 1 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;
}
/*