diff -r 3236311a23a5 tools/python/xen/util/xmlrpclib2.py --- a/tools/python/xen/util/xmlrpclib2.py Fri Sep 22 12:14:22 2006 +0100 +++ b/tools/python/xen/util/xmlrpclib2.py Fri Sep 22 12:43:37 2006 +0100 @@ -25,7 +25,6 @@ import fcntl import fcntl from httplib import HTTPConnection, HTTP -from xmlrpclib import Transport from SimpleXMLRPCServer import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler import SocketServer import xmlrpclib, socket, os, stat @@ -81,10 +80,11 @@ class HTTPUnix(HTTP): class HTTPUnix(HTTP): _connection_class = HTTPUnixConnection -class UnixTransport(Transport): +class UnixTransport(xmlrpclib.Transport): def request(self, host, handler, request_body, verbose=0): self.__handler = handler - return Transport.request(self, host, '/RPC2', request_body, verbose) + return xmlrpclib.Transport.request(self, host, '/RPC2', + request_body, verbose) def make_connection(self, host): return HTTPUnix(self.__handler) @@ -134,7 +134,7 @@ class TCPXMLRPCServer(SocketServer.Threa allow_reuse_address = True def __init__(self, addr, requestHandler=XMLRPCRequestHandler, - logRequests=1): + logRequests = 1): SimpleXMLRPCServer.__init__(self, addr, requestHandler, logRequests) flags = fcntl.fcntl(self.fileno(), fcntl.F_GETFD) @@ -201,7 +201,7 @@ class UnixXMLRPCServer(TCPXMLRPCServer): class UnixXMLRPCServer(TCPXMLRPCServer): address_family = socket.AF_UNIX - def __init__(self, addr, logRequests): + def __init__(self, addr, logRequests = 1): parent = os.path.dirname(addr) if os.path.exists(parent): os.chown(parent, os.geteuid(), os.getegid()) diff -r 3236311a23a5 tools/python/xen/xend/server/SrvDaemon.py --- a/tools/python/xen/xend/server/SrvDaemon.py Fri Sep 22 12:14:22 2006 +0100 +++ b/tools/python/xen/xend/server/SrvDaemon.py Fri Sep 22 12:44:03 2006 +0100 @@ -195,6 +195,8 @@ class Daemon: sig) else: self.run(w and os.fdopen(w, 'w') or None) + # if we reach here, the child should quit. + os._exit(0) return ret @@ -290,6 +292,8 @@ class Daemon: relocate.listenRelocation() servers = SrvServer.create() servers.start(status) + del servers + except Exception, ex: print >>sys.stderr, 'Exception starting xend:', ex if XEND_DEBUG: diff -r 3236311a23a5 tools/python/xen/xend/server/SrvServer.py --- a/tools/python/xen/xend/server/SrvServer.py Fri Sep 22 12:14:22 2006 +0100 +++ b/tools/python/xen/xend/server/SrvServer.py Fri Sep 22 13:09:48 2006 +0100 @@ -42,6 +42,7 @@ import fcntl import time +import signal from threading import Thread from xen.web.httpserver import HttpServer, UnixHttpServer @@ -54,7 +55,6 @@ from SrvRoot import SrvRoot from SrvRoot import SrvRoot from XMLRPCServer import XMLRPCServer - xroot = XendRoot.instance() @@ -65,6 +65,14 @@ class XendServers: def add(self, server): self.servers.append(server) + + def cleanup(self, signum = 0, frame = None): + log.debug("SrvServer.cleanup()") + for server in self.servers: + try: + server.shutdown() + except: + pass def start(self, status): # Running the network script will spawn another process, which takes @@ -100,8 +108,24 @@ class XendServers: status.write('0') status.close() - for t in threads: - t.join() + # Prepare to catch SIGTERM (received when 'xend stop' is executed) + # and call each server's cleanup if possible + signal.signal(signal.SIGTERM, self.cleanup) + + # 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 = len([t for t in threads if t.isAlive()]) + while runningThreads > 0: + try: + for t in threads: + t.join(1.0) + runningThreads = len([t for t in threads if t.isAlive()]) + except: + pass + def create(): root = SrvDir() diff -r 3236311a23a5 tools/python/xen/xend/server/XMLRPCServer.py --- a/tools/python/xen/xend/server/XMLRPCServer.py Fri Sep 22 12:14:22 2006 +0100 +++ b/tools/python/xen/xend/server/XMLRPCServer.py Fri Sep 22 13:07:32 2006 +0100 @@ -16,16 +16,15 @@ # Copyright (C) 2006 XenSource Ltd. #============================================================================ +from types import ListType import xmlrpclib - -from xen.xend import XendDomain, XendDomainInfo, XendNode, \ - XendLogging, XendDmesg from xen.util.xmlrpclib2 import UnixXMLRPCServer, TCPXMLRPCServer -from xen.xend.XendClient import XML_RPC_SOCKET, ERROR_INVALID_DOMAIN -from xen.xend.XendError import * +from xen.xend import XendDomain, XendDomainInfo, XendNode +from xen.xend import XendLogging, XendDmesg +from xen.xend.XendClient import XML_RPC_SOCKET from xen.xend.XendLogging import log -from types import ListType +from xen.xend.XendError import XendInvalidDomain def lookup(domid): info = XendDomain.instance().domain_lookup_by_name_or_id(domid) @@ -75,8 +74,8 @@ def get_log(): finally: f.close() -methods = ['device_create', 'device_configure', 'destroyDevice', - 'getDeviceSxprs', +methods = ['device_create', 'device_configure', + 'destroyDevice','getDeviceSxprs', 'setMemoryTarget', 'setName', 'setVCpuCount', 'shutdown', 'send_sysrq', 'getVCPUInfo', 'waitForDevices', 'getRestartCount'] @@ -84,25 +83,33 @@ exclude = ['domain_create', 'domain_rest exclude = ['domain_create', 'domain_restore'] class XMLRPCServer: - def __init__(self, use_tcp=False): - self.ready = False + def __init__(self, use_tcp=False, host = "localhost", port = 8006, + path = XML_RPC_SOCKET): self.use_tcp = use_tcp + self.port = port + self.host = host + self.path = path + + self.ready = False + self.running = True def run(self): if self.use_tcp: - # bind to something fixed for now as we may eliminate - # tcp support completely. - self.server = TCPXMLRPCServer(("localhost", 8005), logRequests=False) + self.server = TCPXMLRPCServer((self.host, self.port), + logRequests = False) else: - self.server = UnixXMLRPCServer(XML_RPC_SOCKET, False) + self.server = UnixXMLRPCServer(self.path, logRequests = False) + + # Legacy deprecated xm xmlrpc api + # -------------------------------------------------------------------- # Functions in XendDomainInfo for name in methods: fn = eval("lambda domid, *args: dispatch(domid, '%s', args)"%name) self.server.register_function(fn, "xend.domain.%s" % name) - # Functions in XendDomain inst = XendDomain.instance() + for name in dir(inst): fn = getattr(inst, name) if name.startswith("domain_") and callable(fn): @@ -126,4 +133,20 @@ class XMLRPCServer: self.server.register_introspection_functions() self.ready = True - self.server.serve_forever() + + # 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() + + def cleanup(self): + log.debug("XMLRPCServer.cleanup()") + + def shutdown(self): + self.running = False + self.ready = False +