Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion ext/io/event/selector/uring.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ struct IO_Event_Selector_URing_Completion
struct IO_Event_List list;

struct IO_Event_Selector_URing_Waiting *waiting;
bool operation_pending;
bool cancellation_pending;
};

Expand Down Expand Up @@ -207,10 +208,12 @@ struct IO_Event_Selector_URing_Completion * IO_Event_Selector_URing_Completion_a
if (DEBUG_COMPLETION) fprintf(stderr, "IO_Event_Selector_URing_Completion_acquire(%p, limit=%ld)\n", (void*)completion, selector->completions.limit);

assert(completion->waiting == NULL);
assert(!completion->operation_pending);
assert(!completion->cancellation_pending);

waiting->completion = completion;
completion->waiting = waiting;
completion->operation_pending = true;

return completion;
}
Expand All @@ -230,6 +233,7 @@ inline static
void IO_Event_Selector_URing_Completion_recycle(struct IO_Event_Selector_URing *selector, struct IO_Event_Selector_URing_Completion *completion)
{
assert(completion->waiting == NULL);
assert(!completion->operation_pending);
assert(!completion->cancellation_pending);

IO_Event_List_prepend(&selector->free_list, &completion->list);
Expand All @@ -240,6 +244,9 @@ void IO_Event_Selector_URing_Completion_complete(struct IO_Event_Selector_URing
{
if (DEBUG_COMPLETION) fprintf(stderr, "IO_Event_Selector_URing_Completion_complete(%p)\n", (void*)completion);

assert(completion->operation_pending);
completion->operation_pending = false;

IO_Event_Selector_URing_Completion_cancel(completion);

// A cancellation SQE still refers to this completion record. Keep it out of
Expand All @@ -257,7 +264,7 @@ void IO_Event_Selector_URing_Completion_cancellation_complete(struct IO_Event_Se
assert(completion->cancellation_pending);
completion->cancellation_pending = false;

if (completion->waiting == NULL) {
if (!completion->operation_pending) {
IO_Event_Selector_URing_Completion_recycle(selector, completion);
}
}
Expand All @@ -283,6 +290,7 @@ void IO_Event_Selector_URing_Completion_initialize(void *element)
IO_Event_List_initialize(&completion->list);
completion->list.type = &IO_Event_Selector_URing_Completion_Type;
completion->waiting = NULL;
completion->operation_pending = false;
completion->cancellation_pending = false;
}

Expand Down
1 change: 1 addition & 0 deletions releases.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## Unreleased

- Fix the `URing` completion free-list empty check so its sole entry can be reused instead of unnecessarily allocating a new completion.
- Keep cancelled `URing` completion records allocated until both the operation and cancellation completions have been processed.

## v1.20.0

Expand Down
38 changes: 38 additions & 0 deletions test/io/event/selector/cancellable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,44 @@
selector.select(0.1)
end
end

it "can reuse completions after cancelling waits" do
skip "Requires the URing selector" unless defined?(IO::Event::Selector::URing) && selector.is_a?(IO::Event::Selector::URing)

pid = Process.fork do
local_selector = selector.class.new(Fiber.current)
local_input, local_output = IO.pipe

begin
cancelled_waiter = Fiber.new do
local_selector.io_wait(Fiber.current, local_input, IO::READABLE)
rescue Interrupt
# The pending wait was cancelled.
end

cancelled_waiter.transfer
cancelled_waiter.raise(Interrupt)
local_selector.select(0.01)

waiters = 2.times.map do
Fiber.new do
local_selector.io_wait(Fiber.current, local_input, IO::READABLE)
rescue Interrupt
# The pending wait was cancelled.
end
end

waiters.each(&:transfer)
ensure
local_selector.close
local_input.close
local_output.close
end
end

_, status = Process.wait2(pid)
expect(status).to be(:success?)
end
end
end

Expand Down
Loading