Skip to content

Commit d3f7198

Browse files
committed
Go back to using the original, self-pipe based implementation of interruptible
This is looking like the most likely culprit of a memory leak pointed out for multiple people on #330
1 parent 95dc9b4 commit d3f7198

File tree

3 files changed

+17
-64
lines changed

3 files changed

+17
-64
lines changed

lib/solid_queue/engine.rb

-8
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,5 @@ class Engine < ::Rails::Engine
3737
include ActiveJob::ConcurrencyControls
3838
end
3939
end
40-
41-
initializer "solid_queue.include_interruptible_concern" do
42-
if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3.2")
43-
SolidQueue::Processes::Base.include SolidQueue::Processes::Interruptible
44-
else
45-
SolidQueue::Processes::Base.include SolidQueue::Processes::OgInterruptible
46-
end
47-
end
4840
end
4941
end

lib/solid_queue/processes/interruptible.rb

+17-17
Original file line numberDiff line numberDiff line change
@@ -2,36 +2,36 @@
22

33
module SolidQueue::Processes
44
module Interruptible
5-
include SolidQueue::AppExecutor
6-
75
def wake_up
86
interrupt
97
end
108

119
private
10+
SELF_PIPE_BLOCK_SIZE = 11
1211

1312
def interrupt
14-
queue << true
13+
self_pipe[:writer].write_nonblock(".")
14+
rescue Errno::EAGAIN, Errno::EINTR
15+
# Ignore writes that would block and retry
16+
# if another signal arrived while writing
17+
retry
1518
end
1619

17-
# Sleeps for 'time'. Can be interrupted asynchronously and return early via wake_up.
18-
# @param time [Numeric, Duration] the time to sleep. 0 returns immediately.
1920
def interruptible_sleep(time)
20-
# Invoking this from the main thread may result in significant slowdown.
21-
# Utilizing asynchronous execution (Futures) addresses this performance issue.
22-
Concurrent::Promises.future(time) do |timeout|
23-
queue.clear unless queue.pop(timeout:).nil?
24-
end.on_rejection! do |e|
25-
wrapped_exception = RuntimeError.new("Interruptible#interruptible_sleep - #{e.class}: #{e.message}")
26-
wrapped_exception.set_backtrace(e.backtrace)
27-
handle_thread_error(wrapped_exception)
28-
end.value
21+
if time > 0 && self_pipe[:reader].wait_readable(time)
22+
loop { self_pipe[:reader].read_nonblock(SELF_PIPE_BLOCK_SIZE) }
23+
end
24+
rescue Errno::EAGAIN, Errno::EINTR
25+
end
2926

30-
nil
27+
# Self-pipe for signal-handling (http://cr.yp.to/docs/selfpipe.html)
28+
def self_pipe
29+
@self_pipe ||= create_self_pipe
3130
end
3231

33-
def queue
34-
@queue ||= Queue.new
32+
def create_self_pipe
33+
reader, writer = IO.pipe
34+
{ reader: reader, writer: writer }
3535
end
3636
end
3737
end

lib/solid_queue/processes/og_interruptible.rb

-39
This file was deleted.

0 commit comments

Comments
 (0)