mirror of
https://github.com/ruby/ruby.git
synced 2026-01-27 04:24:23 +00:00
Avoid race condition in test_without_handle_interrupt_signal_works. (#15504)
This commit is contained in:
parent
ff831eb057
commit
e2fe0aae43
Notes:
git
2025-12-12 09:13:09 +00:00
Merged-By: ioquatix <samuel@codeotaku.com>
@ -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);
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user