diff --git a/lib/bunny/exceptions.rb b/lib/bunny/exceptions.rb index 0a202f91a..c00efc194 100644 --- a/lib/bunny/exceptions.rb +++ b/lib/bunny/exceptions.rb @@ -97,6 +97,12 @@ def initialize(frame) end end + class ConnectionAlreadyClosed < Exception + def initialize + super('Connection has been already closed') + end + end + class ShutdownSignal < Exception end diff --git a/lib/bunny/session.rb b/lib/bunny/session.rb index e895fe455..f6e88cd10 100644 --- a/lib/bunny/session.rb +++ b/lib/bunny/session.rb @@ -325,6 +325,7 @@ def start @status_mutex.synchronize { @status = :not_connected } raise TCPConnectionFailedForAllHosts end + @status_mutex.synchronize { @manually_closed = false } self end @@ -343,6 +344,7 @@ def transport_write_timeout # @return [Bunny::Channel] Newly opened channel def create_channel(n = nil, consumer_pool_size = 1, consumer_pool_abort_on_exception = false, consumer_pool_shutdown_timeout = 60) raise ArgumentError, "channel number 0 is reserved in the protocol and cannot be used" if 0 == n + raise ConnectionAlreadyClosed if manually_closed? @channel_mutex.synchronize do if n && (ch = @channels[n]) @@ -369,7 +371,10 @@ def close clean_up_on_shutdown end - @status_mutex.synchronize { @status = :closed } + @status_mutex.synchronize do + @status = :closed + @manually_closed = true + end end alias stop close @@ -404,6 +409,11 @@ def closed? @status_mutex.synchronize { @status == :closed } end + # @return [Boolean] true if this AMQP 0.9.1 connection has been programmatically closed + def manually_closed? + @status_mutex.synchronize { @manually_closed == true } + end + # @return [Boolean] true if this AMQP 0.9.1 connection is open def open? @status_mutex.synchronize do diff --git a/spec/issues/issue465_spec.rb b/spec/issues/issue465_spec.rb new file mode 100644 index 000000000..efbb83a72 --- /dev/null +++ b/spec/issues/issue465_spec.rb @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +require 'spec_helper' + +describe Bunny::Session do + let(:connection) do + c = Bunny.new( + user: 'bunny_gem', password: 'bunny_password', + vhost: 'bunny_testbed', + port: ENV.fetch('RABBITMQ_PORT', 5672) + ) + c.start + c + end + + context 'after the connection has been manually closed' do + before :each do + connection.close + end + + after :each do + connection.close if connection.open? + end + + describe '#create_channel' do + it 'should raise an exception' do + expect { + connection.create_channel + }.to raise_error(Bunny::ConnectionAlreadyClosed) + end + end + end +end