diff --git a/tools/python/xen/util/xmlrpclib2.py b/tools/python/xen/util/xmlrpclib2.py index 3ba1b259b1..ac95d4cf39 100644 --- a/tools/python/xen/util/xmlrpclib2.py +++ b/tools/python/xen/util/xmlrpclib2.py @@ -256,6 +256,7 @@ class UnixXMLRPCRequestHandler(XMLRPCRequestHandler): class UnixXMLRPCServer(TCPXMLRPCServer): address_family = socket.AF_UNIX + allow_address_reuse = True def __init__(self, addr, allowed, xenapi, logRequests = 1): mkdir.parents(os.path.dirname(addr), stat.S_IRWXU, True) diff --git a/tools/python/xen/web/httpserver.py b/tools/python/xen/web/httpserver.py index 2326a2b875..14965e418f 100644 --- a/tools/python/xen/web/httpserver.py +++ b/tools/python/xen/web/httpserver.py @@ -294,8 +294,6 @@ class HttpServer: backlog = 5 - closed = False - def __init__(self, root, interface, port=8080): self.root = root self.interface = interface @@ -303,6 +301,7 @@ class HttpServer: # ready indicates when we are ready to begin accept connections # it should be set after a successful bind self.ready = False + self.closed = False def run(self): self.bind() @@ -317,7 +316,6 @@ class HttpServer: def stop(self): self.close() - def bind(self): self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) flags = fcntl.fcntl(self.socket.fileno(), fcntl.F_GETFD) @@ -334,7 +332,10 @@ class HttpServer: def close(self): self.closed = True + self.ready = False try: + # shutdown socket explicitly to allow reuse + self.socket.shutdown(socket.SHUT_RDWR) self.socket.close() except: pass @@ -345,6 +346,9 @@ class HttpServer: def getResource(self, req): return self.root.getRequestResource(req) + def shutdown(self): + self.close() + class UnixHttpServer(HttpServer): diff --git a/tools/python/xen/xend/server/SrvServer.py b/tools/python/xen/xend/server/SrvServer.py index 9810f2896e..d4aae088e6 100644 --- a/tools/python/xen/xend/server/SrvServer.py +++ b/tools/python/xen/xend/server/SrvServer.py @@ -65,6 +65,7 @@ class XendServers: def __init__(self, root): self.servers = [] self.root = root + self.running = False self.cleaningUp = False self.reloadingConfig = False @@ -79,6 +80,7 @@ class XendServers: server.shutdown() except: pass + self.running = False def reloadConfig(self, signum = 0, frame = None): log.debug("SrvServer.reloadConfig()") @@ -107,13 +109,12 @@ class XendServers: if server.ready: continue - thread = Thread(target=server.run, name=server.__class__.__name__) - if isinstance(server, HttpServer): - thread.setDaemon(True) + thread = Thread(target=server.run, + name=server.__class__.__name__) + thread.setDaemon(True) thread.start() threads.append(thread) - # check for when all threads have initialized themselves and then # close the status pipe @@ -143,42 +144,27 @@ class XendServers: status.close() status = None - # Interruptible Thread.join - Python Bug #1167930 - # Replaces: for t in threads: t.join() - # Reason: The above will cause python signal handlers to be - # blocked so we're not able to catch SIGTERM in any - # way for cleanup - runningThreads = threads - while len(runningThreads) > 0: - try: - for t in threads: - t.join(1.0) - runningThreads = [t for t in threads - if t.isAlive() and not t.isDaemon()] - if self.cleaningUp and len(runningThreads) > 0: - log.debug("Waiting for %s." % - [x.getName() for x in runningThreads]) - except: - pass - + # loop to keep main thread alive until it receives a SIGTERM + self.running = True + while self.running: + time.sleep(100000000) + if self.reloadingConfig: log.info("Restarting all XML-RPC and Xen-API servers...") self.cleaningUp = False self.reloadingConfig = False xoptions.set_config() - new_servers = [x for x in self.servers - if isinstance(x, HttpServer)] - self.servers = new_servers + self.servers = [] _loadConfig(self, self.root, True) else: break def _loadConfig(servers, root, reload): - if not reload and xoptions.get_xend_http_server(): + if xoptions.get_xend_http_server(): servers.add(HttpServer(root, xoptions.get_xend_address(), xoptions.get_xend_port())) - if not reload and xoptions.get_xend_unix_server(): + if xoptions.get_xend_unix_server(): path = xoptions.get_xend_unix_path() log.info('unix path=' + path) servers.add(UnixHttpServer(root, path)) diff --git a/tools/python/xen/xend/server/XMLRPCServer.py b/tools/python/xen/xend/server/XMLRPCServer.py index 05646fcea6..130da9aea8 100644 --- a/tools/python/xen/xend/server/XMLRPCServer.py +++ b/tools/python/xen/xend/server/XMLRPCServer.py @@ -179,21 +179,24 @@ class XMLRPCServer: # Custom runloop so we can cleanup when exiting. # ----------------------------------------------------------------- try: - self.server.socket.settimeout(1.0) while self.running: self.server.handle_request() finally: - self.cleanup() + self.shutdown() def cleanup(self): - log.debug("XMLRPCServer.cleanup()") + log.debug('XMLRPCServer.cleanup()') try: - self.server.socket.close() + if hasattr(self, 'server'): + # shutdown socket explicitly to allow reuse + self.server.socket.shutdown(socket.SHUT_RDWR) + self.server.socket.close() except Exception, exn: log.exception(exn) pass def shutdown(self): self.running = False - self.ready = False - + if self.ready: + self.ready = False + self.cleanup()