Robust socket reconnect?

Imagine 2 servers, exchanging data every minute, so a good idea is
to just leave a connection open.
But sometimes the net goes strange ways, connection is lost and one
has to reconnect.

That would be done like...

t = Thread.new(....) do |...|
  begin
    socket = TCPSocket::open(someip,someport)
    loop do
      ...
      whatever
      ...
      break if done
    end
  rescue *ErrorsOnSocket => err # socket errors, see ruby-talk:127627
    socket.close # cleanup
    sleep 60 # 1 min recovery
    retry # reconnect
  rescue Exception => ex # general bug
    puts "BUG in xyz!"
    puts "#{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}"
    raise
  ensure
    socket.close
  end
end

- Is the cleanup by just doing a socket.close the correct way? Are really
all Ruby internal data structures cleaned up afterwards and we don't
silently leak file descriptors and/or bet on the gc to clean up (soon)?

- Anybody else had the same problem - any (more sophisticated) code to
showcase? :slight_smile:

tnx!
Martin

"Martin Pirker" <crf@sbox.tu-graz.ac.at> schrieb im Newsbeitrag news:4203e766$0$8024$3b214f66@aconews.univie.ac.at...

Imagine 2 servers, exchanging data every minute, so a good idea is
to just leave a connection open.
But sometimes the net goes strange ways, connection is lost and one
has to reconnect.

That would be done like...

t = Thread.new(....) do |...|
begin
   socket = TCPSocket::open(someip,someport)
   loop do
     ...
     whatever
     ...
     break if done
   end
rescue *ErrorsOnSocket => err # socket errors, see ruby-talk:127627
   socket.close # cleanup
   sleep 60 # 1 min recovery
   retry # reconnect
rescue Exception => ex # general bug
   puts "BUG in xyz!"
   puts "#{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}"
   raise
ensure
   socket.close
end
end

- Is the cleanup by just doing a socket.close the correct way? Are really
all Ruby internal data structures cleaned up afterwards and we don't
silently leak file descriptors and/or bet on the gc to clean up (soon)?

- Anybody else had the same problem - any (more sophisticated) code to
showcase? :slight_smile:

I'd structure the code a bit differently:

t = Thread.new(....) do |...|
  begin
    TCPSocket::open(someip,someport) do |socket|
      loop do
        ...
        whatever
        ...
        break if done
      end
    end
  rescue *ErrorsOnSocket => err # socket errors, see ruby-talk:127627
# no close because that is done by the block already
    sleep 60 # 1 min recovery
    retry # reconnect
# I'd put this general code at a much higher level as
# you rethrow anyway:
  rescue Exception => ex # general bug
    puts "BUG in xyz!"
    puts "#{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}"
    raise
  end
end

Now the code is significantly shorter and cleaner (when you remove my comments and the other code :-))

Kind regards

    robert