| Index: third_party/twisted_8_1/twisted/runner/procmon.py
|
| diff --git a/third_party/twisted_8_1/twisted/runner/procmon.py b/third_party/twisted_8_1/twisted/runner/procmon.py
|
| deleted file mode 100644
|
| index 5bd84284eecd65a0a3dfba5438d7c79de899169e..0000000000000000000000000000000000000000
|
| --- a/third_party/twisted_8_1/twisted/runner/procmon.py
|
| +++ /dev/null
|
| @@ -1,235 +0,0 @@
|
| -# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
|
| -# See LICENSE for details.
|
| -
|
| -#
|
| -"""
|
| -ProcessMonitor: run processes, monitor progress, and restart when
|
| -they die.
|
| -
|
| -The ProcessMonitor will not attempt to restart a process that appears
|
| -to die instantly -- with each "instant" death (less than 1 second, by
|
| -default), it will delay approximately twice as long before restarting
|
| -it. A successful run will reset the counter.
|
| -
|
| -The primary interface is "addProcess" and "removeProcess". When the
|
| -service is active (that is, when the application it is attached to
|
| -is running), adding a process automatically starts it.
|
| -
|
| -Each process has a name (a string). This string must uniquely identify
|
| -the process. In particular, attempting to add two processes with the
|
| -same name will result in a key error.
|
| -
|
| -The arguments to addProcess are:
|
| - - name -- a string, uniquely specifying the process
|
| - - args -- a list of arguments. the first will be used to determine the
|
| - executable
|
| - - optionally, the uid and gid this process should be run as (by default,
|
| - it does not change uid/gid before running processes).
|
| -
|
| -Note that args are passed to the system call, not to the shell. If running
|
| -the shell is desired, the common idiom is to use
|
| -.addProcess("name", ['/bin/sh', '-c', shell_script])
|
| -
|
| -removeProcess takes just the name argument. If the process is started, it
|
| -kills it, and will never restart it.
|
| -
|
| -The "restartAll" method restarts all processes. This is useful for 3rd
|
| -parties management services to allow a user to restart servers because
|
| -of an outside circumstances change -- for example, a new version of a library
|
| -which is installed.
|
| -
|
| -The following attributes on the monitor can be set to configure behaviour
|
| - - threshold -- how long a process has to live before the death is considered
|
| - instant (default 1, measured in seconds)
|
| - - killTime -- how long a process being killed has to get its affairs in
|
| - order before it gets killed with an unmaskable signal
|
| - (default 5, measured in seconds)
|
| - - consistencyDelay -- time between consistency checks
|
| - (default 60, measured in seconds)
|
| -"""
|
| -
|
| -import os, time
|
| -from signal import SIGTERM, SIGKILL
|
| -from twisted.python import log
|
| -from twisted.internet import protocol, reactor, process
|
| -from twisted.application import service
|
| -from twisted.protocols import basic
|
| -
|
| -class DummyTransport:
|
| -
|
| - disconnecting = 0
|
| -
|
| -transport = DummyTransport()
|
| -
|
| -class LineLogger(basic.LineReceiver):
|
| -
|
| - tag = None
|
| - delimiter = '\n'
|
| -
|
| - def lineReceived(self, line):
|
| - log.msg('[%s] %s' % (self.tag, line))
|
| -
|
| -class LoggingProtocol(protocol.ProcessProtocol):
|
| -
|
| - service = None
|
| - name = None
|
| - empty = 1
|
| -
|
| - def connectionMade(self):
|
| - self.output = LineLogger()
|
| - self.output.tag = self.name
|
| - self.output.makeConnection(transport)
|
| -
|
| - def outReceived(self, data):
|
| - self.output.dataReceived(data)
|
| - self.empty = data[-1] == '\n'
|
| -
|
| - errReceived = outReceived
|
| -
|
| - def processEnded(self, reason):
|
| - if not self.empty:
|
| - self.output.dataReceived('\n')
|
| - self.service.connectionLost(self.name)
|
| -
|
| -
|
| -class ProcessMonitor(service.Service):
|
| -
|
| - threshold = 1
|
| - active = 0
|
| - killTime = 5
|
| - consistency = None
|
| - consistencyDelay = 60
|
| -
|
| - def __init__(self):
|
| - self.processes = {}
|
| - self.protocols = {}
|
| - self.delay = {}
|
| - self.timeStarted = {}
|
| - self.murder = {}
|
| -
|
| - def __getstate__(self):
|
| - dct = service.Service.__getstate__(self)
|
| - for k in ('active', 'consistency'):
|
| - if dct.has_key(k):
|
| - del dct[k]
|
| - dct['protocols'] = {}
|
| - dct['delay'] = {}
|
| - dct['timeStarted'] = {}
|
| - dct['murder'] = {}
|
| - return dct
|
| -
|
| - def _checkConsistency(self):
|
| - for name, protocol in self.protocols.items():
|
| - proc = protocol.transport
|
| - try:
|
| - proc.signalProcess(0)
|
| - except (OSError, process.ProcessExitedAlready):
|
| - log.msg("Lost process %r somehow, restarting." % name)
|
| - del self.protocols[name]
|
| - self.startProcess(name)
|
| - self.consistency = reactor.callLater(self.consistencyDelay,
|
| - self._checkConsistency)
|
| -
|
| - def addProcess(self, name, args, uid=None, gid=None):
|
| - if self.processes.has_key(name):
|
| - raise KeyError("remove %s first" % name)
|
| - self.processes[name] = args, uid, gid
|
| - if self.active:
|
| - self.startProcess(name)
|
| -
|
| - def removeProcess(self, name):
|
| - del self.processes[name]
|
| - self.stopProcess(name)
|
| -
|
| - def startService(self):
|
| - service.Service.startService(self)
|
| - self.active = 1
|
| - for name in self.processes.keys():
|
| - reactor.callLater(0, self.startProcess, name)
|
| - self.consistency = reactor.callLater(self.consistencyDelay,
|
| - self._checkConsistency)
|
| -
|
| - def stopService(self):
|
| - service.Service.stopService(self)
|
| - self.active = 0
|
| - for name in self.processes.keys():
|
| - self.stopProcess(name)
|
| - self.consistency.cancel()
|
| -
|
| - def connectionLost(self, name):
|
| - if self.murder.has_key(name):
|
| - self.murder[name].cancel()
|
| - del self.murder[name]
|
| - if self.protocols.has_key(name):
|
| - del self.protocols[name]
|
| - if time.time()-self.timeStarted[name]<self.threshold:
|
| - delay = self.delay[name] = min(1+2*self.delay.get(name, 0), 3600)
|
| - else:
|
| - delay = self.delay[name] = 0
|
| - if self.active and self.processes.has_key(name):
|
| - reactor.callLater(delay, self.startProcess, name)
|
| -
|
| - def startProcess(self, name):
|
| - if self.protocols.has_key(name):
|
| - return
|
| - p = self.protocols[name] = LoggingProtocol()
|
| - p.service = self
|
| - p.name = name
|
| - args, uid, gid = self.processes[name]
|
| - self.timeStarted[name] = time.time()
|
| - reactor.spawnProcess(p, args[0], args, uid=uid, gid=gid)
|
| -
|
| - def _forceStopProcess(self, proc):
|
| - try:
|
| - proc.signalProcess(SIGKILL)
|
| - except process.ProcessExitedAlready:
|
| - pass
|
| -
|
| - def stopProcess(self, name):
|
| - if not self.protocols.has_key(name):
|
| - return
|
| - proc = self.protocols[name].transport
|
| - del self.protocols[name]
|
| - try:
|
| - proc.signalProcess(SIGTERM)
|
| - except process.ProcessExitedAlready:
|
| - pass
|
| - else:
|
| - self.murder[name] = reactor.callLater(self.killTime, self._forceStopProcess, proc)
|
| -
|
| - def restartAll(self):
|
| - for name in self.processes.keys():
|
| - self.stopProcess(name)
|
| -
|
| - def __repr__(self):
|
| - l = []
|
| - for name, proc in self.processes.items():
|
| - uidgid = ''
|
| - if proc[1] is not None:
|
| - uidgid = str(proc[1])
|
| - if proc[2] is not None:
|
| - uidgid += ':'+str(proc[2])
|
| -
|
| - if uidgid:
|
| - uidgid = '(' + uidgid + ')'
|
| - l.append('%r%s: %r' % (name, uidgid, proc[0]))
|
| - return ('<' + self.__class__.__name__ + ' '
|
| - + ' '.join(l)
|
| - + '>')
|
| -
|
| -def main():
|
| - mon = ProcessMonitor()
|
| - mon.addProcess('foo', ['/bin/sh', '-c', 'sleep 2;echo hello'])
|
| - mon.addProcess('qux', ['/bin/sh', '-c', 'sleep 2;printf pilim'])
|
| - mon.addProcess('bar', ['/bin/sh', '-c', 'echo goodbye'])
|
| - mon.addProcess('baz', ['/bin/sh', '-c',
|
| - 'echo welcome;while :;do echo blah;sleep 5;done'])
|
| - reactor.callLater(30, lambda mon=mon:
|
| - os.kill(mon.protocols['baz'].transport.pid, SIGTERM))
|
| - reactor.callLater(60, mon.restartAll)
|
| - mon.startService()
|
| - reactor.addSystemEventTrigger('before', 'shutdown', mon.stopService)
|
| - reactor.run()
|
| -
|
| -if __name__ == '__main__':
|
| - main()
|
|
|