handle_event blocks main thread even when looped in its own thread
Opened this issue · 1 comments
Hi, even if I loop in a separate thread, handle_event will block the main one. Here's my code:
require 'evdev'
re = Evdev.new('/dev/input/event0')
re.on(:REL_X) { |val| puts "val: #{val}" }
Thread.new do
loop do
begin
re.handle_event
rescue Evdev::AwaitEvent
Kernel.select([re.event_channel])
retry
end
end
end
i = 0
until i > 50
puts i
i += 1
sleep 0.2
end
The way I figure, it should count to 50, during which if I move my rotary encoder it should display the value (given my system configuration, -1 or 1). Instead, the main thread is blocked and the counter only increases if I unblock it by feeding it events (ie rotating my rotary encoder).
$ ruby re-test.rb
WARN: Unresolved specs during Gem::Specification.reset:
linux_input (~> 1.0)
WARN: Clearing out unresolved specs.
Please report a bug if this causes problems.
0
1
val: 1
val: 1
2
val: 1
3
val: -1
val: -1
4
val: -1
5
val: -1
6
val: 1
val: 1
val: 1
7
val: 1
8
val: -1
val: -1
val: -1
9
val: -1
10
val: 1
val: 1
val: 1
val: 1
^C^C^C^C^C # then I moved the rotary encoder and fed it an event
Traceback (most recent call last):
re-test.rb: Interrupt
It even traps SIGINT so I can't stop my program with Ctrl-C until I unblock handle_event by rotating the encoder.
I've tried all possible parameters for handle_event: the default (:blocking) but also :normal, :sync and :force_sync.
How can I listen to events while I'm doing other stuff?
Try replacing the loop in your Thread:
require 'evdev'
re = Evdev.new('/dev/input/event0')
re.on(:REL_X) { |val| puts "val: #{val}" }
Thread.new do
loop do
while re.events_pending? do
re.handle_event
end
Kernel.select([re.event_channel])
end
end
i = 0
until i > 50
puts i
i += 1
sleep 0.2
end
I completely removed the rescue for Evdev::AwaitEvent, because as far as I can tell it never happens. handle_event
seems to completely block other threads so I only call it if I know I have events_pending?
. Kernel.select
seems to wait, but does not block other threads. I think this does what you are looking for.
[Update: Replaced if
with while
. I think that should do it.]