[PATCH stateful-chg] commandserver: move _socket state to handler

Jun Wu quark at fb.com
Wed May 17 17:39:48 UTC 2017


# HG changeset patch
# User Jun Wu <quark at fb.com>
# Date 1495042747 25200
#      Wed May 17 10:39:07 2017 -0700
# Node ID 28a79744e54d6b9c08d8d835c5bafdc90ba3c02d
# Parent  37bcb4665529f5cc59b8dffb1014ac0cab37492c
# Available At https://bitbucket.org/quark-zju/hg-draft
#              hg pull https://bitbucket.org/quark-zju/hg-draft -r 28a79744e54d
commandserver: move _socket state to handler

This patch moves "_socket" state service to servicehandler. It makes
"_socket" replace-able inside service main loop, which is needed for
stateful chg to be functional without subclassing the service class.

diff --git a/mercurial/chgserver.py b/mercurial/chgserver.py
--- a/mercurial/chgserver.py
+++ b/mercurial/chgserver.py
@@ -479,5 +479,5 @@ def _hashaddress(address, hashstr):
     return '%s-%s' % (os.path.join(dirname, basename), hashstr)
 
-class chgunixservicehandler(object):
+class chgunixservicehandler(commandserver.unixservicehandler):
     """Set of operations for chg services"""
 
@@ -485,5 +485,5 @@ class chgunixservicehandler(object):
 
     def __init__(self, ui):
-        self.ui = ui
+        super(chgunixservicehandler, self).__init__(ui)
         self._idletimeout = ui.configint('chgserver', 'idletimeout', 3600)
         self._lastactive = time.time()
diff --git a/mercurial/commandserver.py b/mercurial/commandserver.py
--- a/mercurial/commandserver.py
+++ b/mercurial/commandserver.py
@@ -407,4 +407,5 @@ class unixservicehandler(object):
     def __init__(self, ui):
         self.ui = ui
+        self._socket = None
 
     def bindsocket(self, sock, address):
@@ -414,4 +415,19 @@ class unixservicehandler(object):
         self.ui.flush()  # avoid buffering of status message
 
+    def getsocket(self):
+        """Return a socket for the server to use. Create on demand.
+
+        This will be called inside service's main loop per iteration. A
+        different socket can be returned and service can use that in a new
+        iteration. Make sure the returned one is the only one opened."""
+        if self._socket is None:
+            self._socket = socket.socket(socket.AF_UNIX)
+        return self._socket
+
+    def closesocket(self):
+        if self._socket is not None:
+            self._socket.close()
+            self._socket = None
+
     def unlinksocket(self, address):
         os.unlink(address)
@@ -444,5 +460,4 @@ class unixforkingservice(object):
             raise error.Abort(_('no socket path specified with --address'))
         self._servicehandler = handler or unixservicehandler(ui)
-        self._sock = None
         self._oldsigchldhandler = None
         self._workerpids = set()  # updated by signal handler; do not iterate
@@ -450,6 +465,6 @@ class unixforkingservice(object):
 
     def init(self):
-        self._sock = socket.socket(socket.AF_UNIX)
-        self._servicehandler.bindsocket(self._sock, self.address)
+        sock = self._servicehandler.getsocket()
+        self._servicehandler.bindsocket(sock, self.address)
         o = signal.signal(signal.SIGCHLD, self._sigchldhandler)
         self._oldsigchldhandler = o
@@ -463,5 +478,5 @@ class unixforkingservice(object):
     def _cleanup(self):
         signal.signal(signal.SIGCHLD, self._oldsigchldhandler)
-        self._sock.close()
+        self._servicehandler.closesocket()
         self._unlinksocket()
         # don't kill child processes as they have active clients, just wait
@@ -486,6 +501,7 @@ class unixforkingservice(object):
                 self._unlinksocket()
                 exiting = True
+            sock = self._servicehandler.getsocket()
             try:
-                ready = select.select([self._sock], [], [], h.pollinterval)[0]
+                ready = select.select([sock], [], [], h.pollinterval)[0]
                 if not ready:
                     # only exit if we completed all queued requests
@@ -493,5 +509,5 @@ class unixforkingservice(object):
                         break
                     continue
-                conn, _addr = self._sock.accept()
+                conn, _addr = sock.accept()
             except (select.error, socket.error) as inst:
                 if inst.args[0] == errno.EINTR:


More information about the Mercurial-devel mailing list