Skip to content

Commit 2c043d2

Browse files
committed
Merge pull request #502 from redis/fix-timeout-inconsistency
Fix inconsistent connections when using Timeout under MRI 2.1+.
2 parents d43b06e + e7e681e commit 2c043d2

File tree

3 files changed

+45
-13
lines changed

3 files changed

+45
-13
lines changed

lib/redis/client.rb

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ def initialize(options = {})
7777
@connection = nil
7878
@command_map = {}
7979

80+
@pending_reads = 0
81+
8082
if options.include?(:sentinels)
8183
@connector = Connector::Sentinel.new(@options)
8284
else
@@ -243,12 +245,15 @@ def io
243245

244246
def read
245247
io do
246-
connection.read
248+
value = connection.read
249+
@pending_reads -= 1
250+
value
247251
end
248252
end
249253

250254
def write(command)
251255
io do
256+
@pending_reads += 1
252257
connection.write(command)
253258
end
254259
end
@@ -315,6 +320,7 @@ def establish_connection
315320
@options[:port] = server[:port]
316321

317322
@connection = @options[:driver].connect(server)
323+
@pending_reads = 0
318324
rescue TimeoutError,
319325
Errno::ECONNREFUSED,
320326
Errno::EHOSTDOWN,
@@ -326,6 +332,8 @@ def establish_connection
326332
end
327333

328334
def ensure_connected
335+
disconnect if @pending_reads > 0
336+
329337
attempts = 0
330338

331339
begin

test/connection_handling_test.rb

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,4 +186,25 @@ def test_config_set
186186
r.config :set, "timeout", 300
187187
end
188188
end
189+
190+
driver(:ruby, :hiredis) do
191+
def test_consistency_on_multithreaded_env
192+
t = nil
193+
194+
commands = {
195+
:set => lambda { |key, value| t.kill; "+OK\r\n" },
196+
:incr => lambda { |key| ":1\r\n" },
197+
}
198+
199+
redis_mock(commands) do |redis|
200+
t = Thread.new do
201+
redis.set("foo", "bar")
202+
end
203+
204+
t.join
205+
206+
assert_equal 1, redis.incr("baz")
207+
end
208+
end
209+
end
189210
end

test/support/redis_mock.rb

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,23 @@ def shutdown
2424
end
2525

2626
def run
27-
loop do
28-
session = @server.accept
29-
30-
begin
31-
return if yield(session) == :exit
32-
ensure
33-
session.close
27+
begin
28+
loop do
29+
session = @server.accept
30+
31+
begin
32+
return if yield(session) == :exit
33+
ensure
34+
session.close
35+
end
3436
end
37+
rescue => ex
38+
$stderr.puts "Error running mock server: #{ex.message}" if VERBOSE
39+
$stderr.puts ex.backtrace if VERBOSE
40+
retry
41+
ensure
42+
@server.close
3543
end
36-
rescue => ex
37-
$stderr.puts "Error running mock server: #{ex.message}" if VERBOSE
38-
$stderr.puts ex.backtrace if VERBOSE
39-
ensure
40-
@server.close
4144
end
4245
end
4346

0 commit comments

Comments
 (0)