From e2fe0aae43fee4815c1fc0896a2f03de35bfd873 Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Fri, 12 Dec 2025 22:12:41 +1300 Subject: [PATCH] Avoid race condition in `test_without_handle_interrupt_signal_works`. (#15504) --- ext/-test-/scheduler/scheduler.c | 13 ++++++++----- .../scheduler/test_interrupt_with_scheduler.rb | 9 +++------ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/ext/-test-/scheduler/scheduler.c b/ext/-test-/scheduler/scheduler.c index f3badceb92..f8384f597e 100644 --- a/ext/-test-/scheduler/scheduler.c +++ b/ext/-test-/scheduler/scheduler.c @@ -1,5 +1,6 @@ #include "ruby/ruby.h" #include "ruby/thread.h" +#include "ruby/io.h" #include "ruby/fiber/scheduler.h" /* @@ -24,6 +25,7 @@ */ struct blocking_state { + int notify_descriptor; volatile int interrupted; }; @@ -39,14 +41,14 @@ blocking_operation(void *argument) { struct blocking_state *blocking_state = (struct blocking_state *)argument; - while (true) { - struct timeval tv = {1, 0}; // 1 second timeout. + write(blocking_state->notify_descriptor, "x", 1); + while (!blocking_state->interrupted) { + struct timeval tv = {1, 0}; // 1 second timeout. int result = select(0, NULL, NULL, NULL, &tv); if (result == -1 && errno == EINTR) { blocking_state->interrupted = 1; - return NULL; } // Otherwise, timeout -> loop again. @@ -56,9 +58,10 @@ blocking_operation(void *argument) } static VALUE -scheduler_blocking_loop(VALUE self) +scheduler_blocking_loop(VALUE self, VALUE notify) { struct blocking_state blocking_state = { + .notify_descriptor = rb_io_descriptor(notify), .interrupted = 0, }; @@ -84,5 +87,5 @@ Init_scheduler(void) VALUE mBug = rb_define_module("Bug"); VALUE mScheduler = rb_define_module_under(mBug, "Scheduler"); - rb_define_module_function(mScheduler, "blocking_loop", scheduler_blocking_loop, 0); + rb_define_module_function(mScheduler, "blocking_loop", scheduler_blocking_loop, 1); } diff --git a/test/-ext-/scheduler/test_interrupt_with_scheduler.rb b/test/-ext-/scheduler/test_interrupt_with_scheduler.rb index 42a109b98b..eb7a0647e5 100644 --- a/test/-ext-/scheduler/test_interrupt_with_scheduler.rb +++ b/test/-ext-/scheduler/test_interrupt_with_scheduler.rb @@ -26,23 +26,20 @@ class TestSchedulerInterruptHandling < Test::Unit::TestCase # Yield to the scheduler: sleep(0) - output.puts "ready" - Bug::Scheduler.blocking_loop + Bug::Scheduler.blocking_loop(output) end end output.close - assert_equal "ready\n", input.gets + assert_equal "x", input.read(1) - sleep 0.1 # Ensure the child is in the blocking loop - # $stderr.puts "Sending interrupt" Process.kill(:INT, pid) reaper = Thread.new do Process.waitpid2(pid) end - unless reaper.join(1) + unless reaper.join(10) Process.kill(:KILL, pid) end