Avoid race condition in test_without_handle_interrupt_signal_works. (#15504)

This commit is contained in:
Samuel Williams 2025-12-12 22:12:41 +13:00 committed by GitHub
parent ff831eb057
commit e2fe0aae43
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
Notes: git 2025-12-12 09:13:09 +00:00
Merged-By: ioquatix <samuel@codeotaku.com>
2 changed files with 11 additions and 11 deletions

View File

@ -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);
}

View File

@ -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