Skip to content

Commit e2fe0aa

Browse files
authored
Avoid race condition in test_without_handle_interrupt_signal_works. (#15504)
1 parent ff831eb commit e2fe0aa

File tree

2 files changed

+11
-11
lines changed

2 files changed

+11
-11
lines changed

ext/-test-/scheduler/scheduler.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "ruby/ruby.h"
22
#include "ruby/thread.h"
3+
#include "ruby/io.h"
34
#include "ruby/fiber/scheduler.h"
45

56
/*
@@ -24,6 +25,7 @@
2425
*/
2526

2627
struct blocking_state {
28+
int notify_descriptor;
2729
volatile int interrupted;
2830
};
2931

@@ -39,14 +41,14 @@ blocking_operation(void *argument)
3941
{
4042
struct blocking_state *blocking_state = (struct blocking_state *)argument;
4143

42-
while (true) {
43-
struct timeval tv = {1, 0}; // 1 second timeout.
44+
write(blocking_state->notify_descriptor, "x", 1);
4445

46+
while (!blocking_state->interrupted) {
47+
struct timeval tv = {1, 0}; // 1 second timeout.
4548
int result = select(0, NULL, NULL, NULL, &tv);
4649

4750
if (result == -1 && errno == EINTR) {
4851
blocking_state->interrupted = 1;
49-
return NULL;
5052
}
5153

5254
// Otherwise, timeout -> loop again.
@@ -56,9 +58,10 @@ blocking_operation(void *argument)
5658
}
5759

5860
static VALUE
59-
scheduler_blocking_loop(VALUE self)
61+
scheduler_blocking_loop(VALUE self, VALUE notify)
6062
{
6163
struct blocking_state blocking_state = {
64+
.notify_descriptor = rb_io_descriptor(notify),
6265
.interrupted = 0,
6366
};
6467

@@ -84,5 +87,5 @@ Init_scheduler(void)
8487
VALUE mBug = rb_define_module("Bug");
8588
VALUE mScheduler = rb_define_module_under(mBug, "Scheduler");
8689

87-
rb_define_module_function(mScheduler, "blocking_loop", scheduler_blocking_loop, 0);
90+
rb_define_module_function(mScheduler, "blocking_loop", scheduler_blocking_loop, 1);
8891
}

test/-ext-/scheduler/test_interrupt_with_scheduler.rb

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,23 +26,20 @@ def test_without_handle_interrupt_signal_works
2626
# Yield to the scheduler:
2727
sleep(0)
2828

29-
output.puts "ready"
30-
Bug::Scheduler.blocking_loop
29+
Bug::Scheduler.blocking_loop(output)
3130
end
3231
end
3332

3433
output.close
35-
assert_equal "ready\n", input.gets
34+
assert_equal "x", input.read(1)
3635

37-
sleep 0.1 # Ensure the child is in the blocking loop
38-
# $stderr.puts "Sending interrupt"
3936
Process.kill(:INT, pid)
4037

4138
reaper = Thread.new do
4239
Process.waitpid2(pid)
4340
end
4441

45-
unless reaper.join(1)
42+
unless reaper.join(10)
4643
Process.kill(:KILL, pid)
4744
end
4845

0 commit comments

Comments
 (0)