Reputation: 17920
I am trying to do signal handling for my CLI app. I would like to avoid the self-pipe "trick", but also consider that using a per thread list of signals that is periodically polled is not the best idea. Hence, my idea was to use Queue
to block until a new signal arrives. Here is my attempt:
class CLI
def initialize
@manager = Thread.new { sleep }
@signal_queue = Queue.new
setup_signal_handlers
end
def run
loop do
signal = @signal_queue.pop # This doesn't unblock!
handle_signal(signal)
end
rescue Interrupt
exit
end
private
def handle_signal(signal)
case signal
when 'INT'
raise Interrupt
end
end
def setup_signal_handlers
%w(INT).each do |signal|
trap signal do
@signal_queue.push signal # This works. @signal_queue.size is incremented
end
end
end
end
# Run with CLI.new.run and hit ctrl^C
where I've simplified @manager
for clarity. The problem is that, even if the signal is trapped and pushed to @signal_queue
, the blocking call @signal_queue.pop
doesn't pick it up. What am I missing here?
Upvotes: 0
Views: 323
Reputation: 568
It looks like you're experiencing Ruby bug #12405: Queue doesn't work inside of trap. Luckily this bug got fixed in Ruby versions 2.2.7, 2.3.4, and 2.4.1 (2.5.0 already includes that fix); therefore your code behaves as expected after upgrading to a more recent Ruby version.
Upvotes: 1