[CalendarServer-changes] [5496] CalendarServer/trunk/calendarserver/tap/caldav.py
source_changes at macosforge.org
source_changes at macosforge.org
Tue Apr 20 13:21:24 PDT 2010
Revision: 5496
http://trac.macosforge.org/projects/calendarserver/changeset/5496
Author: sagen at apple.com
Date: 2010-04-20 13:21:23 -0700 (Tue, 20 Apr 2010)
Log Message:
-----------
Have the master process wait for the child processes to stop before shutting itself down.
Modified Paths:
--------------
CalendarServer/trunk/calendarserver/tap/caldav.py
Modified: CalendarServer/trunk/calendarserver/tap/caldav.py
===================================================================
--- CalendarServer/trunk/calendarserver/tap/caldav.py 2010-04-20 20:14:01 UTC (rev 5495)
+++ CalendarServer/trunk/calendarserver/tap/caldav.py 2010-04-20 20:21:23 UTC (rev 5496)
@@ -40,6 +40,8 @@
from twisted.python.usage import Options, UsageError
from twisted.python.reflect import namedClass
from twisted.plugin import IPlugin
+from twisted.internet.defer import Deferred, gatherResults
+from twisted.internet import error, reactor
from twisted.internet.reactor import callLater, addSystemEventTrigger
from twisted.internet.process import ProcessExitedAlready
from twisted.internet.protocol import Protocol, Factory
@@ -141,8 +143,9 @@
self.logObserver.start()
def stopService(self):
- MultiService.stopService(self)
+ d = MultiService.stopService(self)
self.logObserver.stop()
+ return d
class CalDAVOptions (Options, LoggingMixIn):
@@ -1158,6 +1161,7 @@
self._extraFDs = {}
from twisted.internet import reactor
self.reactor = reactor
+ self.stopping = False
def addProcessObject(self, process, env):
@@ -1208,6 +1212,36 @@
self._checkConsistency
)
+ def stopService(self):
+ """
+ Return a deferred that fires when all child processes have ended
+ """
+
+ Service.stopService(self)
+
+ self.stopping = True
+ self.active = 0
+ self.consistency.cancel()
+
+ self.deferreds = { }
+ for name in self.processes.keys():
+ self.deferreds[name] = Deferred()
+ self.stopProcess(name)
+
+ return gatherResults(self.deferreds.values())
+
+ def processEnded(self, name):
+ """
+ When a child process has ended it calls me so I can fire the
+ appropriate deferred which was created in stopService
+ """
+
+ if self.stopping:
+ deferred = self.deferreds.get(name, None)
+ if deferred is not None:
+ deferred.callback(None)
+
+
def signalAll(self, signal, startswithname=None):
"""
Send a signal to all child processes.
@@ -1258,8 +1292,43 @@
childFDs=childFDs
)
+ def _forceStopProcess(self, proc, name):
+ """
+ After self.killTime seconds has passed, this method sends a KILL
+ to the process. Clean up the now-called murder deferred.
+ """
+ try:
+ # This deferred has fired so remove it to keep from trying to
+ # cancel it later
+ del self.murder[name]
+ except KeyError:
+ pass
+ try:
+ proc.signalProcess('KILL')
+ except error.ProcessExitedAlready:
+ pass
+ def stopProcess(self, name):
+ """
+ Stop the process gently at first (TERM), but schedule a KILL for
+ self.killTime seconds later.
+ """
+
+ if not self.protocols.has_key(name):
+ return
+ proc = self.protocols[name].transport
+ del self.protocols[name]
+ try:
+ proc.signalProcess('TERM')
+ except error.ProcessExitedAlready:
+ pass
+ else:
+ self.murder[name] = reactor.callLater(self.killTime, self._forceStopProcess, proc, name)
+
+
+
+
class DelayedStartupLineLogger(object):
"""
A line logger that can handle very long lines.
@@ -1326,6 +1395,12 @@
self.output = DelayedStartupLineLogger()
self.output.tag = self.name
+ def processEnded(self, reason):
+ """
+ Let the service know that this child process has ended
+ """
+ procmon.LoggingProtocol.processEnded(self, reason)
+ self.service.processEnded(self.name)
def getSSLPassphrase(*ignored):
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20100420/2790cfb0/attachment-0001.html>
More information about the calendarserver-changes
mailing list