Skip to content

Commit

Permalink
Add interruptible sleep to avoid deadlocking (#53)
Browse files Browse the repository at this point in the history
* Add interruptible sleep to avoid deadlocking

Stolen from rosa in SolidQueue

* use permit_concurrent_loads just in case
  • Loading branch information
npezza93 authored Dec 17, 2024
1 parent 869bbd2 commit 8640a42
Showing 1 changed file with 40 additions and 3 deletions.
43 changes: 40 additions & 3 deletions lib/action_cable/subscription_adapter/solid_cable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,16 +50,22 @@ def initialize(event_loop)
end

def listen
while running?
loop do
break unless running?

with_polling_volume { broadcast_messages }

sleep ::SolidCable.polling_interval
interruptible_sleep ::SolidCable.polling_interval
end
end

def shutdown
self.running = false
Thread.pass while thread.alive?
wake_up

ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
thread&.join
end
end

def add_channel(channel, on_success)
Expand Down Expand Up @@ -112,6 +118,37 @@ def with_polling_volume
yield
end
end

def wake_up
interrupt
end

SELF_PIPE_BLOCK_SIZE = 11

def interrupt
self_pipe[:writer].write_nonblock(".")
rescue Errno::EAGAIN, Errno::EINTR
# Ignore writes that would block and retry
# if another signal arrived while writing
retry
end

def interruptible_sleep(time)
if time > 0 && self_pipe[:reader].wait_readable(time)
loop { self_pipe[:reader].read_nonblock(SELF_PIPE_BLOCK_SIZE) }
end
rescue Errno::EAGAIN, Errno::EINTR
end

# Self-pipe for signal-handling (http://cr.yp.to/docs/selfpipe.html)
def self_pipe
@self_pipe ||= create_self_pipe
end

def create_self_pipe
reader, writer = IO.pipe
{ reader: reader, writer: writer }
end
end
end
end
Expand Down

0 comments on commit 8640a42

Please sign in to comment.