[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[minion-cvs] Run in a reasonable daemon mode; fork less; lock a litt...



Update of /home/minion/cvsroot/src/minion/lib/mixminion/server
In directory moria.mit.edu:/tmp/cvs-serv27308/lib/mixminion/server

Modified Files:
	Queue.py ServerConfig.py ServerMain.py 
Log Message:
Run in a reasonable daemon mode; fork less; lock a little; be less verbose when we are not verbose.

Index: Queue.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/server/Queue.py,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- Queue.py	12 Dec 2002 19:56:47 -0000	1.2
+++ Queue.py	15 Dec 2002 05:55:30 -0000	1.3
@@ -245,7 +245,7 @@
                 if s[stat.ST_MTIME] < allowedTime:
                     self.__changeState(m[4:], "inp", "rmv")
                     rmv.append(os.path.join(self.dir, m))
-        _secureDelete_bg(rmv, cleanFile)
+	secureDelete(rmv, blocking=1)
         return 0
 
     def __changeState(self, handle, s1, s2):
@@ -463,7 +463,11 @@
 
 def _secureDelete_bg(files, cleanFile):
     """Helper method: delete files in another thread, removing 'cleanFile'
-       once we're done."""
+       once we're done.
+
+       XXXX No longer used: cleanup is a lot faster than it once was, now
+       XXXX that we no longer overwrite repeatedly.  If we reinstate it,
+       XXXX it should be a separate process, not a frequent forker."""
 
     pid = os.fork()
     if pid != 0:

Index: ServerConfig.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/server/ServerConfig.py,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- ServerConfig.py	12 Dec 2002 19:56:47 -0000	1.1
+++ ServerConfig.py	15 Dec 2002 05:55:30 -0000	1.2
@@ -32,6 +32,13 @@
         mixminion.Config._ConfigFile.__init__(self, fname, string)
 
     def validate(self, sections, entries, lines, contents):
+	# Pre-emptively configure the log before validation, so we don't
+	# write to the terminal if we've been asked not to.
+	if not sections['Server'].get("EchoMessages", 0):
+	    LOG.handlers = []
+	    # ???? This can't be the best way to do this.
+
+	# Now, validate the host section.
 	mixminion.Config._validateHostSection(sections.get('Host', {}))
 	# Server section
 	server = sections['Server']
@@ -86,6 +93,7 @@
                      'LogFile' : ('ALLOW', None, None),
                      'LogLevel' : ('ALLOW', C._parseSeverity, "WARN"),
                      'EchoMessages' : ('ALLOW', C._parseBoolean, "no"),
+		     'NoDaemon' : ('ALLOW', C._parseBoolean, "no"),
                      'EncryptIdentityKey' : ('REQUIRE', C._parseBoolean, "yes"),
 		     'IdentityKeyBits': ('ALLOW', C._parseInt, "2048"),
                      'PublicKeyLifetime' : ('ALLOW', C._parseInterval,

Index: ServerMain.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/server/ServerMain.py,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- ServerMain.py	15 Dec 2002 04:15:38 -0000	1.3
+++ ServerMain.py	15 Dec 2002 05:55:30 -0000	1.4
@@ -10,6 +10,7 @@
 
 __all__ = [ 'MixminonServer' ]
 
+import fcntl
 import getopt
 import os
 import sys
@@ -24,8 +25,8 @@
 import mixminion.server.ServerConfig
 import mixminion.server.ServerKeys
 
-from mixminion.Common import LOG, MixError, MixFatalError, ceilDiv, \
-     formatBase64, formatTime, waitForChildren
+from mixminion.Common import LOG, LogStream, MixError, MixFatalError, ceilDiv,\
+     createPrivateDir, formatBase64, formatTime, waitForChildren
 
 class IncomingQueue(mixminion.server.Queue.DeliveryQueue):
     """A DeliveryQueue to accept messages from incoming MMTP connections,
@@ -186,6 +187,21 @@
 	"""Create a new server from a ServerConfig."""
 	LOG.debug("Initializing server")
 	self.config = config
+	homeDir = config['Server']['Homedir']
+	createPrivateDir(homeDir)
+
+	# Lock file.
+	# FFFF Refactor this part into common?
+	self.lockFile = os.path.join(homeDir, "lock")
+	self.lockFD = os.open(self.lockFile, os.O_RDWR|os.O_CREAT, 0600)
+	try:
+	    fcntl.flock(self.lockFD, fcntl.LOCK_EX|fcntl.LOCK_NB)
+	except IOError:
+	    raise MixFatalError("Another server seems to be running.")
+
+	# The pid file.
+	self.pidFile = os.path.join(homeDir, "pid")
+	
 	self.keyring = mixminion.server.ServerKeys.ServerKeyring(config)
 	if self.keyring._getLiveKey() is None:
 	    LOG.info("Generating a month's worth of keys.")
@@ -208,7 +224,6 @@
 	self.moduleManager = config.getModuleManager()
 	self.moduleManager.configure(config)
 
-	homeDir = config['Server']['Homedir']
 	queueDir = os.path.join(homeDir, 'work', 'queues')
 
 	incomingDir = os.path.join(queueDir, "incoming")
@@ -238,10 +253,16 @@
 	self.mmtpServer.connectQueues(incoming=self.incomingQueue,
 				      outgoing=self.outgoingQueue)
 
+
     def run(self):
 	"""Run the server; don't return unless we hit an exception."""
 	# FFFF Use heapq to schedule events? [I don't think so; there are only
 	# FFFF   two events, after all!]
+
+	f = open(self.pidFile, 'wt')
+	f.write("%s\n" % os.getpid())
+	f.close()
+
 	now = time.time()
 	MIX_INTERVAL = 20  # FFFF Configurable!
 	nextMix = now + MIX_INTERVAL
@@ -288,6 +309,13 @@
     def close(self):
 	"""Release all resources; close all files."""
 	self.packetHandler.close()
+	try:
+	    os.unlink(self.lockFile)
+	    fcntl.flock(self.lockFD, fcntl.LOCK_UN)
+	    os.close(self.lockFD)
+	    os.unlink(self.pidFile)
+	except OSError:
+	    pass
 
 #----------------------------------------------------------------------
 def usageAndExit(cmd):
@@ -331,12 +359,25 @@
 	mixminion.Crypto.init_crypto(config)
 
 	server = MixminionServer(config)
+	
     except:
 	LOG.fatal_exc(sys.exc_info(),"Exception while configuring server")
 	print >>sys.stderr, "Shutting down because of exception"
-        #XXXX print stack trace as well as logging?
+	#XXXX001 Print the exception, too.
 	sys.exit(1)
 
+    if not config['Server'].get("NoDaemon",0):
+	print >>sys.stderr, "Starting server in the background"
+	# ??? This 'daemonize' logic should go in Common.
+	pid = os.fork()
+	if pid != 0:
+	    os._exit(0)
+	sys.stderr.close()
+	sys.stdout.close()
+	sys.stdin.close()
+	sys.stdout = LogStream("STDOUT", "WARN")
+	sys.stderr = LogStream("STDERR", "WARN")
+
     LOG.info("Starting server")
     try:
 	server.run()
@@ -344,7 +385,7 @@
 	pass
     except:
 	LOG.fatal_exc(sys.exc_info(),"Exception while running server")
-        #XXXX print stack trace as well as logging?
+	#XXXX001 Print the exception, too.
     LOG.info("Server shutting down")
     server.close()
     LOG.info("Server is shut down")