schoefmann / klarlack

klarlack is a ruby client library for the varnish administration interface. It allows, among other things, purging of cached objects from ruby code.
http://github.com/schoefmax/klarlack
MIT License
73 stars 9 forks source link

Rails freezes when varnish restarts during klarlack request #4

Open grosser opened 14 years ago

grosser commented 14 years ago

10000.times{ EsiHelper.purge_url '^xxxx$' } sudo /etc/i/varnish restart -> Rails instance freezes in 1/3 cases (normal error in 2/3 cases) i already tried removing the mutex + @conn.read + @conn.gets from cmd, but did not help so far

could you write a spec that tests this scenario or just try it out <-> maybe something wrong with our setup...

grosser commented 14 years ago

now we use this in lib/ext/klarlack_hack.rb (only works for non-threading rails...), only the thread will hang, which is not as bad as whole rails hanging...

@conn.write can freeze if varnish restarts

# Timeout does not help...
# so we do it asynchronous (Thread creation takes ~ 40ms)
Varnish::Client # require it ...
module Varnish::Client
  def cmd(name, *params)
    Thread.new do
      begin
        @conn.write "#{name} #{params.join(' ').gsub('\', '\\\')}\n"
        status, length = @conn.gets.split # <status> <content_length>\n
        content = @conn.read(length.to_i + 1) # +1 = \n
        content.chomp!
        raise Error, "Command #{name} returned with status #{status}: #{content}" if status.to_i != 200
          rescue Exception => e
        HoptoadNotifier.notify(e)
      end
    end
  end
end
schoefmann commented 14 years ago

Happy New Year and sorry for the delay.

Looks like a timeout issue to me (I assume you are using timeouts with SystemTimer?) I'll try to reproduce it. Maybe updating the socket code helps - the timeout stuff comes from memcache-client which has since improved it's own code futher. sigh - we could really need a proper socket lib that handles timeouts correctly...

grosser commented 14 years ago

i think the problem is that systemtimer does not get used on REE,

if !defined?(RUBY_ENGINE) require 'system_timer' SystemTimer

but REE has RUBY_ENGINE set to 'ruby', so a check like VERSION =~ 1.8 and not jruby should be better

ATM im using: if RUBY_VERSION =~ /^1\.8\./ and RUBY_PLATFORM !~ /java/
schoefmann commented 14 years ago

good catch. This might indeed fix it. I've changed the code accordingly and pushed the updated gem.

grosser commented 14 years ago

great, ill remove our monkeypatch and see if it works :)