Unable to rescue Errno::ECONNRESET during


#1

For some reason my rescue clause is not catching this exception. Here’s
the stack trace:

/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/openssl/buffering.rb:35:in
sysread': Connection reset by peer (Errno::ECONNRESET) from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/openssl/buffering.rb:35:infill_rbuff’
from
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/openssl/buffering.rb:106:in
gets' from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/net/imap.rb:991:inget_response’
from
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/net/imap.rb:929:in
receive_responses' from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/net/imap.rb:922:ininitialize’
from
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/net/imap.rb:921:in
start' from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/net/imap.rb:921:ininitialize’
from batch/test.rb:6:in new' from batch/test.rb:6 from batch/test.rb:4:inloop’
from batch/test.rb:4

This is the line in test.rb where the error occurs:
imap = Net::IMAP.new(‘imap.gmail.com’, 993, true)

Here’s my test code:

loop do
begin
imap = Net::IMAP.new(‘imap.gmail.com’, 993, true)
imap.login(‘xxxxx’, ‘yyyyy’)
imap.select(‘Inbox’)
imap.expunge
imap.logout
$stdout.putc ‘.’
$stdout.flush
rescue Net::IMAP::NoResponseError => e
puts “IMAP no response”
rescue Net::IMAP::ByeResponseError => e
# send to log file, db, or email
puts “IMAP bye response”
rescue Errno::ECONNRESET => e
puts “Connection reset by peer”
puts e.backtrace
rescue Exception => e
puts “IMAP Error-#{e.class}\n#{e.message}”
puts e.backtrace
end
sleep 1
end

Either the Errno::RCONNRESET or the the Exception clause should catch
the exception, print the error and continue right? But each time it hits
the ECONNRESET error, it terminates. Any idea why?

Thanks a bunch!


#2

What’s interesting is that line 929 of net/imap.rb is in the backtrace:

def receive_responses
  while true
    begin
      resp = get_response             # line 929
    rescue Exception
      @sock.close
      @client_thread.raise($!)
      break
    end

It looks like the exception should be caught here, and explicitly
re-raised in another thread from line 932. You could try adding some
STDERR debugging before and after the get_response line, and inside the
rescue Exception clause.

Maybe “@sock.close” should be “@sock.close rescue nil” in case another
exception is raised then. But line 931 isn’t in the backtrace.

Raising and catching the exception in another thread ought to work as
far as I can see:

class Foo
def initialize
t = Thread.current
Thread.start do
t.raise Errno::ECONNRESET
end.join
end
end

begin
f = Foo.new
rescue Errno::ECONNRESET
puts “Caught it: #{$!.backtrace.join(”\n")}"
end