From 180020e1e53b96a3080f3ac731cb32bbbdee31d5 Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Sat, 6 Dec 2025 20:35:08 +1300 Subject: [PATCH] Fix `io_pwrite` fiber scheduler hook. (#15428) Fix io_pwrite fiber scheduler hook. --- io.c | 13 ++++++++++--- scheduler.c | 8 ++++++-- vm_dump.c | 2 +- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/io.c b/io.c index 549e7e1317..91537895d2 100644 --- a/io.c +++ b/io.c @@ -6254,6 +6254,14 @@ internal_pwrite_func(void *_arg) { struct prdwr_internal_arg *arg = _arg; + return (VALUE)pwrite(arg->fd, arg->buf, arg->count, arg->offset); +} + +static VALUE +pwrite_internal_call(VALUE _arg) +{ + struct prdwr_internal_arg *arg = (struct prdwr_internal_arg *)_arg; + VALUE scheduler = rb_fiber_scheduler_current(); if (scheduler != Qnil) { VALUE result = rb_fiber_scheduler_io_pwrite_memory(scheduler, arg->io->self, arg->offset, arg->buf, arg->count, 0); @@ -6263,8 +6271,7 @@ internal_pwrite_func(void *_arg) } } - - return (VALUE)pwrite(arg->fd, arg->buf, arg->count, arg->offset); + return rb_io_blocking_region_wait(arg->io, internal_pwrite_func, arg, RUBY_IO_WRITABLE); } /* @@ -6316,7 +6323,7 @@ rb_io_pwrite(VALUE io, VALUE str, VALUE offset) arg.buf = RSTRING_PTR(tmp); arg.count = (size_t)RSTRING_LEN(tmp); - n = (ssize_t)rb_io_blocking_region_wait(fptr, internal_pwrite_func, &arg, RUBY_IO_WRITABLE); + n = (ssize_t)pwrite_internal_call((VALUE)&arg); if (n < 0) rb_sys_fail_path(fptr->pathv); rb_str_tmp_frozen_release(str, tmp); diff --git a/scheduler.c b/scheduler.c index 8351fc9945..3e45cbe83e 100644 --- a/scheduler.c +++ b/scheduler.c @@ -460,12 +460,14 @@ rb_fiber_scheduler_current_for_threadptr(rb_thread_t *thread) } } -VALUE -rb_fiber_scheduler_current(void) +VALUE rb_fiber_scheduler_current(void) { + RUBY_ASSERT(ruby_thread_has_gvl_p()); + return rb_fiber_scheduler_current_for_threadptr(GET_THREAD()); } +// This function is allowed to be called without holding the GVL. VALUE rb_fiber_scheduler_current_for_thread(VALUE thread) { return rb_fiber_scheduler_current_for_threadptr(rb_thread_ptr(thread)); @@ -929,6 +931,8 @@ fiber_scheduler_io_pwrite(VALUE _argument) { VALUE rb_fiber_scheduler_io_pwrite(VALUE scheduler, VALUE io, rb_off_t from, VALUE buffer, size_t length, size_t offset) { + + if (!rb_respond_to(scheduler, id_io_pwrite)) { return RUBY_Qundef; } diff --git a/vm_dump.c b/vm_dump.c index c1a8d70735..e2b4804ab0 100644 --- a/vm_dump.c +++ b/vm_dump.c @@ -1436,7 +1436,7 @@ rb_vm_bugreport(const void *ctx, FILE *errout) "---------------------------------------------------\n"); kprintf("Total ractor count: %u\n", vm->ractor.cnt); kprintf("Ruby thread count for this ractor: %u\n", rb_ec_ractor_ptr(ec)->threads.cnt); - if (rb_fiber_scheduler_get() != Qnil) { + if (ec->thread_ptr->scheduler != Qnil) { kprintf("Note that the Fiber scheduler is enabled\n"); } kputs("\n");