Skip to content

Commit eefe348

Browse files
authored
Merge pull request #20 from braze-inc/FOUND-112-prevent-timeout-induced-data-corruption
[FOUND-112] Close open connections on Timeout::Error
2 parents ab1b859 + 9f79720 commit eefe348

File tree

1 file changed

+15
-1
lines changed

1 file changed

+15
-1
lines changed

lib/dalli/server.rb

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,21 @@ def request(op, *args)
8383
Dalli.logger.error "You are trying to cache a Ruby object which cannot be serialized to memcached."
8484
Dalli.logger.error ex.backtrace.join("\n\t")
8585
false
86-
rescue Dalli::DalliError, Dalli::NetworkError, Dalli::ValueOverMaxSize, Timeout::Error
86+
rescue Timeout::Error
87+
# A Timeout::Error can be injected asynchronously by Thread#raise
88+
# (from Timeout.timeout's watchdog thread) at ANY point in execution.
89+
# If it fires between write(req) and reading the response for ANY
90+
# operation (GET, SET, DELETE, etc.), the server's response remains
91+
# in the socket's receive buffer. Without closing, the next operation
92+
# reads those stale bytes as if they were its own response.
93+
#
94+
# Closing the socket discards any potentially stale data and forces
95+
# a fresh connection on the next operation. This may occasionally
96+
# close a clean socket (if the timeout fired at a "safe" point), but
97+
# the performance cost of an extra reconnect is negligible.
98+
close
99+
raise
100+
rescue Dalli::DalliError, Dalli::NetworkError, Dalli::ValueOverMaxSize
87101
raise
88102
rescue => ex
89103
Dalli.logger.error "Unexpected exception during Dalli request: #{ex.class.name}: #{ex.message}"

0 commit comments

Comments
 (0)