Revision f3aebf6f

b/lib/rpc/client.py
204 204

  
205 205
  def _SendMethodCall(self, data):
206 206
    # Send request and wait for response
207
    try:
207
    def send(try_no):
208
      if try_no:
209
        logging.debug("RPC peer disconnected, retrying")
208 210
      self._InitTransport()
209 211
      return self.transport.Call(data)
210
    except Exception:
211
      self._CloseTransport()
212
      raise
212
    return t.Transport.RetryOnBrokenPipe(send, lambda _: self._CloseTransport())
213 213

  
214 214
  def Close(self):
215 215
    """Close the underlying connection.
b/lib/rpc/transport.py
27 27

  
28 28
import collections
29 29
import errno
30
import logging
30 31
import socket
31 32
import time
32 33

  
......
177 178
    self.Send(msg)
178 179
    return self.Recv()
179 180

  
181
  @staticmethod
182
  def RetryOnBrokenPipe(fn, on_error):
183
    """Calls a given function, retrying if it fails on the 'Broken pipe' IO
184
    exception.
185

  
186
    This allows to re-establish a broken connection and retry an IO operation.
187

  
188
    The function receives one an integer argument stating the current retry
189
    number, 0 being the first call, 1 being the retry.
190

  
191
    If any exception occurs, on_error is invoked first with the exception given
192
    as an argument. Then, if the exception is 'Broken pipe', the function call
193
    is retried once more.
194

  
195
    """
196
    retries = 2
197
    for try_no in range(0, retries):
198
      try:
199
        return fn(try_no)
200
      except socket.error, ex:
201
        on_error(ex)
202
        # we retry on "Broken pipe", unless it's the last try
203
        if try_no == retries - 1:
204
          raise
205
        elif not (isinstance(ex.args, tuple) and (ex[0] == errno.EPIPE)):
206
          raise
207
      except Exception, ex:
208
        on_error(ex)
209
        raise
210
    assert False # we should never get here
211

  
180 212
  def Close(self):
181 213
    """Close the socket"""
182 214
    if self.socket is not None:

Also available in: Unified diff