Hi,

Martin Povolnwrote:
> And we have discovered then when [ruby] client waits for continuation
> request response,
> it only accepts request for more data and it hangs [infinite wait] when
> it gets error code.
(snip)
> So following patch agains imap.rb from latest ruby 1.8.3 fixes this
> behaviour.

Your patch works fine, but I don't want to add the `tag' argument
to send_*.
How about this patch?

Index: lib/net/imap.rb
===================================================================
RCS file: /var/cvs/src/ruby/lib/net/imap.rb,v
retrieving revision 1.39.2.11
diff -u -r1.39.2.11 imap.rb
--- lib/net/imap.rb	22 Feb 2005 16:58:33 -0000	1.39.2.11
+++ lib/net/imap.rb	25 Sep 2005 01:27:45 -0000
@@ -902,8 +902,8 @@
       @responses = Hash.new([].freeze)
       @tagged_responses = {}
       @response_handlers = []
-      @tagged_response_arrival = new_cond
-      @continuation_request_arrival = new_cond
+      @response_arrival = new_cond
+      @continuation_request = nil
       @logout_command_tag = nil
       @debug_output_bol = true

@@ -934,7 +934,7 @@
             case resp
             when TaggedResponse
               @tagged_responses[resp.tag] = resp
-              @tagged_response_arrival.broadcast
+              @response_arrival.broadcast
               if resp.tag == @logout_command_tag
                 return
               end
@@ -949,7 +949,8 @@
                 raise ByeResponseError, resp.raw_data
               end
             when ContinuationRequest
-              @continuation_request_arrival.signal
+              @continuation_request = resp
+              @response_arrival.broadcast
             end
             @response_handlers.each do |handler|
               handler.call(resp)
@@ -961,10 +962,14 @@
       end
     end

-    def get_tagged_response(tag, cmd)
+    def get_tagged_response(tag)
       until @tagged_responses.key?(tag)
-        @tagged_response_arrival.wait
+        @response_arrival.wait
       end
+      return pick_up_tagged_response(tag)
+    end
+
+    def pick_up_tagged_response(tag)
       resp = @tagged_responses.delete(tag)
       case resp.name
       when /\A(?:NO)\z/ni
@@ -1005,7 +1010,7 @@

     def send_command(cmd, *args, &block)
       synchronize do
-        tag = generate_tag
+        tag = Thread.current[:net_imap_tag] = generate_tag
         put_string(tag + " " + cmd)
         args.each do |i|
           put_string(" ")
@@ -1019,7 +1024,7 @@
           add_response_handler(block)
         end
         begin
-          return get_tagged_response(tag, cmd)
+          return get_tagged_response(tag)
         ensure
           if block
             remove_response_handler(block)
@@ -1088,7 +1093,15 @@

     def send_literal(str)
       put_string("{" + str.length.to_s + "}" + CRLF)
-      @continuation_request_arrival.wait
+      while @continuation_request.nil? &&
+        !@tagged_responses.key?(Thread.current[:net_imap_tag])
+        @response_arrival.wait
+      end
+      if @continuation_request.nil?
+        pick_up_tagged_response(Thread.current[:net_imap_tag])
+        raise ResponseError.new("expected continuation request")
+      end
+      @continuation_request = nil
       put_string(str)
     end


Shugo