From 6afef40663c6b8b9d07cd2c5ce9d86c5698494d7 Mon Sep 17 00:00:00 2001 From: Sampo Kuokkanen Date: Thu, 27 Aug 2026 15:54:10 +0900 Subject: [PATCH 1/2] Add spec for closing the Fiber scheduler at exit Ruby closes the thread's scheduler during teardown, before any at_exit handler runs. Nothing covered that ordering. --- core/fiber/set_scheduler_spec.rb | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/core/fiber/set_scheduler_spec.rb b/core/fiber/set_scheduler_spec.rb index b34aff873..ec0b4e5bf 100644 --- a/core/fiber/set_scheduler_spec.rb +++ b/core/fiber/set_scheduler_spec.rb @@ -52,4 +52,17 @@ Fiber.set_scheduler(nil) Fiber.scheduler.should == nil end + + it "closes the scheduler at exit, before any at_exit handler runs" do + code = <<-RUBY + scheduler = Object.new + [:block, :unblock, :kernel_sleep, :io_wait].each { |m| scheduler.define_singleton_method(m) {} } + scheduler.define_singleton_method(:close) { print "c" } + + at_exit { print "a" } + Fiber.set_scheduler(scheduler) + RUBY + + ruby_exe(code).should == "ca" + end end From 8c9c0f1a44da5c92b608fb75024e85c10e3d7b5e Mon Sep 17 00:00:00 2001 From: Sampo Kuokkanen Date: Thu, 27 Aug 2026 19:45:56 +0900 Subject: [PATCH 2/2] Refactor to make fiber_interrupt a required method on 4.1 --- core/fiber/set_scheduler_spec.rb | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/core/fiber/set_scheduler_spec.rb b/core/fiber/set_scheduler_spec.rb index ec0b4e5bf..64a9d70c6 100644 --- a/core/fiber/set_scheduler_spec.rb +++ b/core/fiber/set_scheduler_spec.rb @@ -3,8 +3,12 @@ require "fiber" describe "Fiber.scheduler" do + required_methods = [:block, :unblock, :kernel_sleep, :io_wait] + ruby_version_is "4.1" do + required_methods << :fiber_interrupt + end + it "validates the scheduler for required methods" do - required_methods = [:block, :unblock, :kernel_sleep, :io_wait] required_methods.each do |missing_method| scheduler = Object.new required_methods.difference([missing_method]).each do |method| @@ -17,7 +21,6 @@ end it "can set and get the scheduler" do - required_methods = [:block, :unblock, :kernel_sleep, :io_wait] scheduler = Object.new required_methods.each do |method| scheduler.define_singleton_method(method) {} @@ -27,7 +30,6 @@ end it "returns the scheduler after setting it" do - required_methods = [:block, :unblock, :kernel_sleep, :io_wait] scheduler = Object.new required_methods.each do |method| scheduler.define_singleton_method(method) {} @@ -37,7 +39,6 @@ end it "can remove the scheduler" do - required_methods = [:block, :unblock, :kernel_sleep, :io_wait] scheduler = Object.new required_methods.each do |method| scheduler.define_singleton_method(method) {} @@ -56,7 +57,7 @@ it "closes the scheduler at exit, before any at_exit handler runs" do code = <<-RUBY scheduler = Object.new - [:block, :unblock, :kernel_sleep, :io_wait].each { |m| scheduler.define_singleton_method(m) {} } + #{required_methods}.each { |m| scheduler.define_singleton_method(m) {} } scheduler.define_singleton_method(:close) { print "c" } at_exit { print "a" }