Index: fedd/fedd.py
===================================================================
--- fedd/fedd.py	(revision 11a08b0e9216a4de8d8e50f742da2911382a40e7)
+++ fedd/fedd.py	(revision 0ea11afb184736a45872959bc88e2cb71e328400)
@@ -21,4 +21,5 @@
 from signal import signal, pause, SIGINT, SIGTERM
 from select import select
+from time import sleep
 import logging
 
@@ -30,5 +31,13 @@
 
 class fedd_server(ThreadingSSLServer):
+    """
+    Interface the fedd services to the XMLRPC and SOAP interfaces
+    """
     def __init__(self, ME, handler, ssl_ctx, impl):
+	"""
+	Create an SSL server that handles the transport in handler using the
+	credentials in ssl_ctx, and interfacing to the implementation of fedd
+	services in fedd.  ME is the host port pair on which to bind.
+	"""
 	ThreadingSSLServer.__init__(self, ME, handler, ssl_ctx)
 	self.impl = impl
@@ -37,4 +46,10 @@
 
 class fedd_soap_handler(BaseHTTPRequestHandler):
+    """
+    Standard connection between SOAP and the fedd services in impl.
+
+    Much of this is boilerplate from 
+    http://www.xml.com/pub/a/ws/2004/01/20/salz.html
+    """
     server_version = "ZSI/2.0 fedd/0.1 " + BaseHTTPRequestHandler.server_version
 
@@ -99,4 +114,10 @@
 
     def soap_dispatch(self, method, req, fid):
+	"""
+	The connection to the implementation, using the  method maps
+
+	The implementation provides a mapping from SOAP method name to the
+	method in the implementation that provides the service.
+	"""
 	if self.server.soap_methods.has_key(method):
 	    try:
@@ -118,4 +139,10 @@
 
 class fedd_xmlrpc_handler(BaseHTTPRequestHandler):
+    """
+    Standard connection between XMLRPC and the fedd services in impl.
+
+    Much of this is boilerplate from 
+    http://www.xml.com/pub/a/ws/2004/01/20/salz.html
+    """
     server_version = "ZSI/2.0 fedd/0.1 " + BaseHTTPRequestHandler.server_version
 
@@ -157,4 +184,10 @@
 
     def xmlrpc_dispatch(self, method, req, fid):
+	"""
+	The connection to the implementation, using the  method maps
+
+	The implementation provides a mapping from XMLRPC method name to the
+	method in the implementation that provides the service.
+	"""
 	if self.server.xmlrpc_methods.has_key(method):
 	    try:
@@ -193,12 +226,15 @@
 		const=sys.stderr, help="Print SOAP exchange to stderr")
 
-servers_active = True
-
-log_params = {\
-	'format': "%(asctime)s %(levelname)-8s %(message)s",\
-	'datefmt': '%a, %d %b %Y %H:%M:%S'\
-    }
+servers_active = True	    # Sub-servers run while this is True
+services = [ ]		    # Service descriptions
+servers = [ ]		    # fedd_server instances instantiated from services
+servers_lock = Lock()	    # Lock to manipulate servers from sub-server threads
 
 def shutdown(sig, frame):
+    """
+    On a signal, stop running sub-servers.  
+    
+    This is connected to signals below
+    """
     global servers_active, flog
     servers_active = False
@@ -206,20 +242,30 @@
 
 def run_server(s):
+    """
+    Operate a subserver, shutting down when servers_active is false.
+
+    Each server (that is host/port/transport triple) has a thread running this
+    function, so each can handle requests independently.  They all call in to
+    the same implementation, which must manage its own synchronization.
+    """
     global servers_active   # Not strictly needed: servers_active is only read
-
-    if s: 
-	while servers_active:
-	    i, o, e = select((s,), (), (), 5.0)
-	    if s in i:
-		s.handle_request()
-
-services = [ ]
-servers = [ ]
+    global servers	    # List of active servers
+    global servers_lock	    # Lock to manipulate servers
+
+    while servers_active:
+	i, o, e = select((s,), (), (), 5.0)
+	if s in i: s.handle_request()
+
+    # Done.  Remove us from the list
+    servers_lock.acquire()
+    servers.remove(s)
+    servers_lock.release()
 
 opts, args = fedd_opts().parse_args()
 
+# Logging setup
 flog = logging.getLogger("fedd")
-ffmt = logging.Formatter("%(asctime)s %(levelname)-8s %(message)s",
-	'%a, %d %b %Y %H:%M:%S')
+ffmt = logging.Formatter("%(asctime)s %(name)s %(message)s",
+	'%d %b %y %H:%M:%S')
 
 if opts.logfile: fh = logging.FileHandler(opts.logfile)
@@ -236,5 +282,5 @@
 flog.addHandler(fh)
 
-
+# Initialize the implementation
 if opts.configfile != None: 
     try:
@@ -247,9 +293,8 @@
     sys.exit("--configfile is required")
 
-SOAP_port = (opts.host, opts.port)
-
 if impl.cert_file == None:
     sys.exit("Must supply certificate file (probably in config)")
 
+# Create the SSL credentials
 ctx = None
 while ctx == None:
@@ -261,4 +306,6 @@
 	    raise
 
+# Walk through the service descriptions and pack them into the services list.
+# That list has the form (transport (host, port)).
 if opts.services:
     for s in opts.services:
@@ -275,4 +322,5 @@
     services.append((opts.transport, (opts.host, opts.port)))
 
+# Create the servers and put them into a list
 for s in services:
     if s[0] == "soap":
@@ -282,11 +330,27 @@
     else: flog.warning("Unknown transport: %s" % s[0])
 
+#  Make sure that there are no malformed servers in the list
+services = [ s for s in services if s ]
+
+# Catch signals
 signal(SIGINT, shutdown)
 signal(SIGTERM, shutdown)
 
+# Start the servers
 for s in servers:
-    if s:
-	t = Thread(target=run_server, args=(s,))
-	t.start()
-
-pause()
+    Thread(target=run_server, args=(s,)).start()
+
+# Main thread waits for signals
+while servers_active:
+    pause()
+
+#Once shutdown starts wait for all the servers to terminate.
+while True:
+    servers_lock.acquire()
+    if len(servers) == 0: 
+	servers_lock.release()
+	flog.info("All servers exited.  Terminating")
+	sys.exit(0)
+    servers_lock.release()
+    sleep(1)
+
