From ac9bcce81f07d1f5cbc5c714a7ec5f1459aa8ed1 Mon Sep 17 00:00:00 2001 From: Andre Foeken Date: Tue, 30 Sep 2014 08:33:09 +0200 Subject: [PATCH 1/2] Fixed issue with reconnect mechanism When an unexpected error happens when reading frames during the open_connection method the mechanism failed to kick in and the connection would never be re-established. --- lib/bunny/exceptions.rb | 2 +- lib/bunny/session.rb | 20 +++++++++++--------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/lib/bunny/exceptions.rb b/lib/bunny/exceptions.rb index 229926c3f..74e50dbb5 100644 --- a/lib/bunny/exceptions.rb +++ b/lib/bunny/exceptions.rb @@ -65,7 +65,7 @@ def initialize(message, connection, connection_close = nil) class TCPConnectionFailed < Exception attr_reader :hostname, :port - def initialize(e, hostname, port) + def initialize(e, hostname=nil, port=nil) m = case e when String then e diff --git a/lib/bunny/session.rb b/lib/bunny/session.rb index 3258efe0d..e5d564951 100644 --- a/lib/bunny/session.rb +++ b/lib/bunny/session.rb @@ -285,7 +285,7 @@ def start @logger.warn "Retrying connection on next host in line: #{@transport.host}:#{@transport.port}" return self.start - rescue Exception + rescue @status_mutex.synchronize { @status = :not_connected } raise end @@ -961,13 +961,14 @@ def open_connection fr # frame timeout means the broker has closed the TCP connection, which it # does per 0.9.1 spec. - rescue Errno::ECONNRESET, ClientTimeout, AMQ::Protocol::EmptyResponseError, EOFError, IOError => e + rescue nil end if frame.nil? - @state = :closed - @logger.error "RabbitMQ closed TCP connection before AMQP 0.9.1 connection was finalized. Most likely this means authentication failure." - raise Bunny::PossibleAuthenticationFailureError.new(self.user, self.vhost, self.password.size) + raise TCPConnectionFailed.new('An empty frame while opening the connection') + # @state = :closed + # @logger.error "RabbitMQ closed TCP connection before AMQP 0.9.1 connection was finalized. Most likely this means authentication failure." + # raise Bunny::PossibleAuthenticationFailureError.new(self.user, self.vhost, self.password.size) end response = frame.decode_payload @@ -1011,13 +1012,14 @@ def open_connection fr # frame timeout means the broker has closed the TCP connection, which it # does per 0.9.1 spec. - rescue Errno::ECONNRESET, ClientTimeout, AMQ::Protocol::EmptyResponseError, EOFError => e + rescue nil end if frame2.nil? - @state = :closed - @logger.warn "RabbitMQ closed TCP connection before AMQP 0.9.1 connection was finalized. Most likely this means authentication failure." - raise Bunny::PossibleAuthenticationFailureError.new(self.user, self.vhost, self.password.size) + raise TCPConnectionFailed.new('An empty frame while opening the connection') + # @state = :closed + # @logger.warn "RabbitMQ closed TCP connection before AMQP 0.9.1 connection was finalized. Most likely this means authentication failure." + # raise Bunny::PossibleAuthenticationFailureError.new(self.user, self.vhost, self.password.size) end connection_open_ok = frame2.decode_payload From fdc915a5e1fd6fdf5b2b46843713f0c353192976 Mon Sep 17 00:00:00 2001 From: Andre Foeken Date: Tue, 30 Sep 2014 10:08:42 +0200 Subject: [PATCH 2/2] Changed the wording of the empty frame exception This reflects the case where older RabbitMQ servers would simply close the connection when authentication failed. --- lib/bunny/session.rb | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/lib/bunny/session.rb b/lib/bunny/session.rb index e5d564951..f4e498953 100644 --- a/lib/bunny/session.rb +++ b/lib/bunny/session.rb @@ -965,10 +965,7 @@ def open_connection nil end if frame.nil? - raise TCPConnectionFailed.new('An empty frame while opening the connection') - # @state = :closed - # @logger.error "RabbitMQ closed TCP connection before AMQP 0.9.1 connection was finalized. Most likely this means authentication failure." - # raise Bunny::PossibleAuthenticationFailureError.new(self.user, self.vhost, self.password.size) + raise TCPConnectionFailed.new('An empty frame was received while opening the connection. In RabbitMQ <= 3.1 this could mean an authentication issue.') end response = frame.decode_payload @@ -1016,10 +1013,7 @@ def open_connection nil end if frame2.nil? - raise TCPConnectionFailed.new('An empty frame while opening the connection') - # @state = :closed - # @logger.warn "RabbitMQ closed TCP connection before AMQP 0.9.1 connection was finalized. Most likely this means authentication failure." - # raise Bunny::PossibleAuthenticationFailureError.new(self.user, self.vhost, self.password.size) + raise TCPConnectionFailed.new('An empty frame was received while opening the connection. In RabbitMQ <= 3.1 this could mean an authentication issue.') end connection_open_ok = frame2.decode_payload