kgio RubyGem user+dev discussion/patches/pulls/bugs/help
 help / color / mirror / code / Atom feed
* handling Timeout.timeout with sockets
       [not found] <CAMKTR6d=LaskRS=WQfveK7ep6FuPohK0C5cAEqZj4cxLVBzvqQ@mail.gmail.com>
@ 2012-05-03  4:55 ` Mike Perham
  2012-05-03  7:10   ` Eric Wong
  0 siblings, 1 reply; 2+ messages in thread
From: Mike Perham @ 2012-05-03  4:55 UTC (permalink / raw)
  To: kgio

Users of dalli are seeing a very rare issue
(https://github.com/mperham/dalli/issues/146) where a Timeout will
cause the client to crash.  They noticed this reproduces the bug:

require 'timeout'
require 'dalli'

Dalli.logger.level = Logger::DEBUG
client = Dalli::Client.new(["127.0.0.1:11211"], :socket_timeout => 0.01)

begin
 Timeout.timeout 0.01 do
   while true
     client.set("test_123", {:test => "123"})
   end
 end
rescue Timeout::Error => e
 puts [e.class.name, e.message]
 puts e.backtrace.join("\n")
end

p client.get("test_123")

I've noticed that my code cannot rescue the Timeout::Error that is
raised and I expect that is by design.  The block should be timed out
after the interval and code within the block should not be able to
rescue and stop that.

However I'm wondering how my network client can recover from that
timeout?  Presumably there is now data to be read on the socket which,
due to the timeout, has not been read, meaning my protocol state
machine is now out of sync, thus leading to the crash.

Should I drain the socket somehow before each operation?  What is the
best way to do this?

mike

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: handling Timeout.timeout with sockets
  2012-05-03  4:55 ` handling Timeout.timeout with sockets Mike Perham
@ 2012-05-03  7:10   ` Eric Wong
  0 siblings, 0 replies; 2+ messages in thread
From: Eric Wong @ 2012-05-03  7:10 UTC (permalink / raw)
  To: kgio

Mike Perham <mperham@gmail.com> wrote:
> I've noticed that my code cannot rescue the Timeout::Error that is
> raised and I expect that is by design.

Yes, it's by design.  Reading timeout.rb (and its
"git log -p --full-diff" history) is enlightening, btw.   You'll also
get better performance if you explicitly specify a class for timeout
to raise (ref: https://bugs.ruby-lang.org/issues/5765)

> However I'm wondering how my network client can recover from that
> timeout?  Presumably there is now data to be read on the socket which,
> due to the timeout, has not been read, meaning my protocol state
> machine is now out of sync, thus leading to the crash.
> 
> Should I drain the socket somehow before each operation?  What is the
> best way to do this?

The easiest way is to open a new socket.

The other way is to _completely_ parse the old response (that timed out)
before reusing the socket.

Do _not_ rely on IO#nread in the io/wait module for this, it's
inherently racy: bytes may arrive after you call IO#nread.  Unless the
protocol changed recently, for memcached (and nearly everything
implemented on top of TCP), you must completely parse the response the
server gives you.

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2012-05-03  7:10 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <CAMKTR6d=LaskRS=WQfveK7ep6FuPohK0C5cAEqZj4cxLVBzvqQ@mail.gmail.com>
2012-05-03  4:55 ` handling Timeout.timeout with sockets Mike Perham
2012-05-03  7:10   ` Eric Wong

Code repositories for project(s) associated with this public inbox

	https://yhbt.net/kgio.git/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).