Permalink
Browse files

Fix race conditions feeding events to all listeners

  • Loading branch information...
ConradIrwin committed Jul 2, 2011
1 parent cb53676 commit 4f0bf50643fa35bc47acd72fe022c956f5f70333
Showing with 33 additions and 2 deletions.
  1. +7 −2 lib/em-imap/connection.rb
  2. +26 −0 spec/client_spec.rb
@@ -103,7 +103,10 @@ def unbind
end end
def fail_all(error, closed=false) def fail_all(error, closed=false)
@listeners.each{ |listener| listener.fail error } # NOTE: Take a shallow clone of the listeners here so that we get guaranteed
# behaviour. We want to fail any listeners that may be added by the errbacks
# of other listeners.
@listeners.clone.each{ |listener| listener.fail error } while @listeners.size > 0
close_connection unless closed close_connection unless closed
end end
@@ -115,7 +118,9 @@ def add_to_listener_pool(listener)
# EM::IMAP::ResponseParser. Each response is a Net::IMAP response # EM::IMAP::ResponseParser. Each response is a Net::IMAP response
# object. (FIXME) # object. (FIXME)
def receive_response(response) def receive_response(response)
@listeners.each{ |listener| listener.receive_event response } # NOTE: Take a shallow clone of the listeners so that if receiving an
# event causes a new listener to be added, it won't receive this response!
@listeners.clone.each{ |listener| listener.receive_event response }
end end
# Await the response that marks the completion of this command, # Await the response that marks the completion of this command,
View
@@ -157,5 +157,31 @@
a.should == true a.should == true
b.should == true b.should == true
end end
it "should fail any commands inserted by errbacks of commands on catastrophic failure" do
a = false
@client.create("Encyclop\xc3\xa6dia").errback do |e|
@client.logout.errback do
a = true
end
end
@connection.fail_all EOFError.new("Testing error")
a.should == true
end
it "should not pass response objects to listeners added in callbacks" do
rs = []
@connection.should_receive(:send_data).with("RUBY0001 SELECT \"[Google Mail]/All Mail\"\r\n")
@client.select("[Google Mail]/All Mail").callback do |response|
@connection.should_receive(:send_data).with("RUBY0002 IDLE\r\n")
@client.idle do |r|
rs << r
end
end
@connection.receive_data "RUBY0001 OK [READ-WRITE] [Google Mail]/All Mail selected. (Success)\r\n"
rs.length.should == 0
@connection.receive_data "+ idling\r\n"
rs.length.should == 1
end
end end
end end

0 comments on commit 4f0bf50

Please sign in to comment.