[27239] in Source-Commits

home help back first fref pref prev next nref lref last post

python-discuss commit: Fix crashes of ndsc caused by EINTR via SIGWINCH

daemon@ATHENA.MIT.EDU (Victor Vasiliev)
Sun Aug 25 07:09:01 2013

Date: Sun, 25 Aug 2013 07:08:54 -0400
From: Victor Vasiliev <vasilvv@MIT.EDU>
Message-Id: <201308251108.r7PB8s2p003312@drugstore.mit.edu>
To: source-commits@MIT.EDU

https://github.com/mit-athena/python-discuss/commit/b720289d2f0eb425fff4f9eee2ee0de1d2461114
commit b720289d2f0eb425fff4f9eee2ee0de1d2461114
Author: Victor Vasiliev <vasilvv@mit.edu>
Date:   Sun Aug 25 06:34:36 2013 -0400

    Fix crashes of ndsc caused by EINTR via SIGWINCH
    
    This creates a wrapper around the socket which automatically retries
    when a system call is interrupted.

 discuss/rpc.py |   42 ++++++++++++++++++++++++++++++++++++++----
 1 files changed, 38 insertions(+), 4 deletions(-)

diff --git a/discuss/rpc.py b/discuss/rpc.py
index c402d71..d9db5a9 100644
--- a/discuss/rpc.py
+++ b/discuss/rpc.py
@@ -41,6 +41,7 @@
 # exported in the header file. On, and the whole suite is written in K&R C.
 #
 
+import errno
 import socket
 from struct import pack, unpack, calcsize
 from functools import partial
@@ -229,11 +230,22 @@ class USPBlock(object):
 class RPCClient(object):
     def __init__(self, server, port, auth = True, timeout = None):
         self.server = socket.getfqdn(server).lower()
-        self.socket = socket.create_connection((server, port), timeout)
+        self.port = port
+        self.auth = auth
+        self.timeout = timeout
+
+        self.connect()
+        self.make_wrapper()
+
+    def connect(self):
+        self.socket = socket.create_connection((self.server, self.port), self.timeout)
         self.socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
 
+        if not hasattr(self, 'wrapper'):
+            self.wrapper = self.socket
+
         auth_block = USPBlock(constants.KRB_TICKET)
-        if auth:
+        if self.auth:
             authenticator = _get_krb5_ap_req( "discuss", self.server )
 
             # Discuss does the same thing for authentication as Moira does: it
@@ -266,11 +278,33 @@ class RPCClient(object):
 
         self.send(auth_block)
 
+    def make_wrapper(self):
+        class SocketWrapper(object):
+            def recv(self2, *args, **kwargs):
+                try:
+                    return self.socket.recv(*args, **kwargs)
+                except socket.error as err:
+                    if err.errno == errno.EINTR:
+                        self2.recv(*arg, **kwargs)
+                    else:
+                        raise err
+
+            def sendall(self2, *args, **kwargs):
+                try:
+                    return self.socket.sendall(*args, **kwargs)
+                except socket.error as err:
+                    if err.errno == errno.EINTR:
+                        self2.sendall(*arg, **kwargs)
+                    else:
+                        raise err
+
+        self.wrapper = SocketWrapper()
+
     def send(self, block):
-        block.send(self.socket)
+        block.send(self.wrapper)
 
     def receive(self):
-        return USPBlock.receive(self.socket)
+        return USPBlock.receive(self.wrapper)
 
     def request(self, block):
         block.block_type += constants.PROC_BASE

home help back first fref pref prev next nref lref last post