direct-io.hg

changeset 13411:dfcd80b56b82

[XEND] Change SrvServer to not require sockets to be non-blocking.

Set all spawned server threads to be daemonic and make sure their
sockets are closed properly using shutdown() and close(), otherwise
reload will complain about the "Address still in use."

Signed-off-by: Alastair Tse <atse@xensource.com>
author Alastair Tse <atse@xensource.com>
date Thu Jan 18 15:52:23 2007 +0000 (2007-01-18)
parents eee24157bad2
children d64601b977b0
files tools/python/xen/util/xmlrpclib2.py tools/python/xen/web/httpserver.py tools/python/xen/xend/server/SrvServer.py tools/python/xen/xend/server/XMLRPCServer.py
line diff
     1.1 --- a/tools/python/xen/util/xmlrpclib2.py	Thu Jan 18 15:34:29 2007 +0000
     1.2 +++ b/tools/python/xen/util/xmlrpclib2.py	Thu Jan 18 15:52:23 2007 +0000
     1.3 @@ -256,6 +256,7 @@ class UnixXMLRPCRequestHandler(XMLRPCReq
     1.4  
     1.5  class UnixXMLRPCServer(TCPXMLRPCServer):
     1.6      address_family = socket.AF_UNIX
     1.7 +    allow_address_reuse = True
     1.8  
     1.9      def __init__(self, addr, allowed, xenapi, logRequests = 1):
    1.10          mkdir.parents(os.path.dirname(addr), stat.S_IRWXU, True)
     2.1 --- a/tools/python/xen/web/httpserver.py	Thu Jan 18 15:34:29 2007 +0000
     2.2 +++ b/tools/python/xen/web/httpserver.py	Thu Jan 18 15:52:23 2007 +0000
     2.3 @@ -294,8 +294,6 @@ class HttpServer:
     2.4  
     2.5      backlog = 5
     2.6  
     2.7 -    closed = False
     2.8 -
     2.9      def __init__(self, root, interface, port=8080):
    2.10          self.root = root
    2.11          self.interface = interface
    2.12 @@ -303,6 +301,7 @@ class HttpServer:
    2.13          # ready indicates when we are ready to begin accept connections
    2.14          # it should be set after a successful bind
    2.15          self.ready = False
    2.16 +        self.closed = False
    2.17  
    2.18      def run(self):
    2.19          self.bind()
    2.20 @@ -317,7 +316,6 @@ class HttpServer:
    2.21      def stop(self):
    2.22          self.close()
    2.23  
    2.24 -
    2.25      def bind(self):
    2.26          self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    2.27          flags = fcntl.fcntl(self.socket.fileno(), fcntl.F_GETFD)
    2.28 @@ -334,7 +332,10 @@ class HttpServer:
    2.29  
    2.30      def close(self):
    2.31          self.closed = True
    2.32 +        self.ready = False
    2.33          try:
    2.34 +            # shutdown socket explicitly to allow reuse
    2.35 +            self.socket.shutdown(socket.SHUT_RDWR)
    2.36              self.socket.close()
    2.37          except:
    2.38              pass
    2.39 @@ -345,6 +346,9 @@ class HttpServer:
    2.40      def getResource(self, req):
    2.41          return self.root.getRequestResource(req)
    2.42  
    2.43 +    def shutdown(self):
    2.44 +        self.close()
    2.45 +
    2.46  
    2.47  class UnixHttpServer(HttpServer):
    2.48  
     3.1 --- a/tools/python/xen/xend/server/SrvServer.py	Thu Jan 18 15:34:29 2007 +0000
     3.2 +++ b/tools/python/xen/xend/server/SrvServer.py	Thu Jan 18 15:52:23 2007 +0000
     3.3 @@ -65,6 +65,7 @@ class XendServers:
     3.4      def __init__(self, root):
     3.5          self.servers = []
     3.6          self.root = root
     3.7 +        self.running = False
     3.8          self.cleaningUp = False
     3.9          self.reloadingConfig = False
    3.10  
    3.11 @@ -79,6 +80,7 @@ class XendServers:
    3.12                  server.shutdown()
    3.13              except:
    3.14                  pass
    3.15 +        self.running = False
    3.16  
    3.17      def reloadConfig(self, signum = 0, frame = None):
    3.18          log.debug("SrvServer.reloadConfig()")
    3.19 @@ -107,13 +109,12 @@ class XendServers:
    3.20                  if server.ready:
    3.21                      continue
    3.22  
    3.23 -                thread = Thread(target=server.run, name=server.__class__.__name__)
    3.24 -                if isinstance(server, HttpServer):
    3.25 -                    thread.setDaemon(True)
    3.26 +                thread = Thread(target=server.run,
    3.27 +                                name=server.__class__.__name__)
    3.28 +                thread.setDaemon(True)
    3.29                  thread.start()
    3.30                  threads.append(thread)
    3.31  
    3.32 -
    3.33              # check for when all threads have initialized themselves and then
    3.34              # close the status pipe
    3.35  
    3.36 @@ -143,42 +144,27 @@ class XendServers:
    3.37                  status.close()
    3.38                  status = None
    3.39  
    3.40 -            # Interruptible Thread.join - Python Bug #1167930
    3.41 -            #   Replaces: for t in threads: t.join()
    3.42 -            #   Reason:   The above will cause python signal handlers to be
    3.43 -            #             blocked so we're not able to catch SIGTERM in any
    3.44 -            #             way for cleanup
    3.45 -            runningThreads = threads
    3.46 -            while len(runningThreads) > 0:
    3.47 -                try:
    3.48 -                    for t in threads:
    3.49 -                        t.join(1.0)
    3.50 -                    runningThreads = [t for t in threads
    3.51 -                                      if t.isAlive() and not t.isDaemon()]
    3.52 -                    if self.cleaningUp and len(runningThreads) > 0:
    3.53 -                        log.debug("Waiting for %s." %
    3.54 -                                  [x.getName() for x in runningThreads])
    3.55 -                except:
    3.56 -                    pass
    3.57 -
    3.58 +            # loop to keep main thread alive until it receives a SIGTERM
    3.59 +            self.running = True
    3.60 +            while self.running:
    3.61 +                time.sleep(100000000)
    3.62 +                
    3.63              if self.reloadingConfig:
    3.64                  log.info("Restarting all XML-RPC and Xen-API servers...")
    3.65                  self.cleaningUp = False
    3.66                  self.reloadingConfig = False
    3.67                  xoptions.set_config()
    3.68 -                new_servers = [x for x in self.servers
    3.69 -                               if isinstance(x, HttpServer)]
    3.70 -                self.servers = new_servers
    3.71 +                self.servers = []
    3.72                  _loadConfig(self, self.root, True)
    3.73              else:
    3.74                  break
    3.75  
    3.76  def _loadConfig(servers, root, reload):
    3.77 -    if not reload and xoptions.get_xend_http_server():
    3.78 +    if xoptions.get_xend_http_server():
    3.79          servers.add(HttpServer(root,
    3.80                                 xoptions.get_xend_address(),
    3.81                                 xoptions.get_xend_port()))
    3.82 -    if not reload and xoptions.get_xend_unix_server():
    3.83 +    if  xoptions.get_xend_unix_server():
    3.84          path = xoptions.get_xend_unix_path()
    3.85          log.info('unix path=' + path)
    3.86          servers.add(UnixHttpServer(root, path))
     4.1 --- a/tools/python/xen/xend/server/XMLRPCServer.py	Thu Jan 18 15:34:29 2007 +0000
     4.2 +++ b/tools/python/xen/xend/server/XMLRPCServer.py	Thu Jan 18 15:52:23 2007 +0000
     4.3 @@ -179,21 +179,24 @@ class XMLRPCServer:
     4.4          # Custom runloop so we can cleanup when exiting.
     4.5          # -----------------------------------------------------------------
     4.6          try:
     4.7 -            self.server.socket.settimeout(1.0)
     4.8              while self.running:
     4.9                  self.server.handle_request()
    4.10          finally:
    4.11 -            self.cleanup()
    4.12 +            self.shutdown()
    4.13  
    4.14      def cleanup(self):
    4.15 -        log.debug("XMLRPCServer.cleanup()")
    4.16 +        log.debug('XMLRPCServer.cleanup()')
    4.17          try:
    4.18 -            self.server.socket.close()
    4.19 +            if hasattr(self, 'server'):
    4.20 +                # shutdown socket explicitly to allow reuse
    4.21 +                self.server.socket.shutdown(socket.SHUT_RDWR)
    4.22 +                self.server.socket.close()
    4.23          except Exception, exn:
    4.24              log.exception(exn)
    4.25              pass
    4.26  
    4.27      def shutdown(self):
    4.28          self.running = False
    4.29 -        self.ready = False
    4.30 -
    4.31 +        if self.ready:
    4.32 +            self.ready = False
    4.33 +            self.cleanup()