X-Git-Url: https://git.llucax.com/software/pymin.git/blobdiff_plain/614b40051120971a022e66d0fe4827ae917f5d0c..66531a5a9a6bfbf91921ec9e9c8b52af4a3624ee:/pymin/procman.py?ds=sidebyside diff --git a/pymin/procman.py b/pymin/procman.py index 359b3c0..2955863 100644 --- a/pymin/procman.py +++ b/pymin/procman.py @@ -6,8 +6,8 @@ import signal import subprocess import logging ; log = logging.getLogger('pymin.procman') -__all__ = ('ProcessManager', 'manager', 'register', 'unregister', 'call', - 'start', 'stop', 'kill', 'get', 'has', 'sigchild_handler') +__all__ = ('ProcessManager', 'manager', 'register', 'unregister', 'once', + 'start', 'stop', 'restart', 'kill', 'get', 'has', 'sigchild_handler') class ProcessInfo: def __init__(self, name, command, callback=None, persist=False, @@ -27,7 +27,6 @@ class ProcessInfo: self.signal = None self.process = None self.error_count = 0 - self.running = False def start(self): assert self.process is None self.restart() @@ -35,7 +34,6 @@ class ProcessInfo: self.clear() log.debug(u'ProcessInfo.restart(): executing %s', self.command) self.process = subprocess.Popen(self.command, *self.args, **self.kwargs) - self.running = True def stop(self): assert self.process is not None self.dont_run = True @@ -51,6 +49,9 @@ class ProcessInfo: assert self.process is not None os.kill(self.process.pid, signum) self.signal = signum + @property + def running(self): + return self.process is not None and self.process.poll() is None def __repr__(self): pid = None if self.process is not None: @@ -71,6 +72,7 @@ class ProcessManager: max_errors=3, *args, **kwargs): log.debug(u'ProcessManager.register(%s, %s, %s, %s, %s, %s, %s)', name, command, callback, persist, max_errors, args, kwargs) + assert not self.has(name) self.services[name] = ProcessInfo(name, command, callback, persist, max_errors, args, kwargs) @@ -82,10 +84,11 @@ class ProcessManager: pi.start() self.namemap[pi.name] = self.pidmap[pi.process.pid] = pi - def call(self, name, command, callback=None, persist=False, + def once(self, name, command, callback=None, persist=False, max_errors=3, *args, **kwargs): - log.debug(u'ProcessManager.call(%s, %s, %s, %s, %s, %s, %s)', + log.debug(u'ProcessManager.once(%s, %s, %s, %s, %s, %s, %s)', name, command, callback, persist, max_errors, args, kwargs) + assert not self.has(name) pi = ProcessInfo(name, command, callback, persist, max_errors, args, kwargs) self._call(pi) @@ -102,12 +105,15 @@ class ProcessManager: def restart(self, name): log.debug(u'ProcessManager.restart(%s)', name) + # we have to check first in namemap in case is an unregistered + # process (added with once()) if name in self.namemap: - self.namemap[name].stop() - self.namemap[name].wait() - self.namemap[name].restart() + pi = self.namemap[name] + pi.stop() + pi.process.wait() + pi.restart() else: - self.namemap[name].start() + self.services[name].start() def kill(self, name, signum): log.debug(u'ProcessManager.kill(%s, %s)', name, signum) @@ -203,9 +209,10 @@ if __name__ == '__main__': manager = ProcessManager() register = manager.register unregister = manager.unregister -call = manager.call +once = manager.once start = manager.start stop = manager.stop +restart = manager.restart kill = manager.kill get = manager.get has = manager.has @@ -236,24 +243,29 @@ if __name__ == '__main__': assert 'test-service-2' not in manager.namemap pm.start('test-service-2') assert 'test-service-2' in manager.namemap + assert get('test-service-2').running print 'died:', pi.name, pi.command register('test-service', ('sleep', '2'), notify, True) assert 'test-service' in manager.services assert 'test-service' not in manager.namemap + assert not get('test-service').running register('test-service-2', ('sleep', '3'), notify, False) assert 'test-service-2' in manager.services assert 'test-service-2' not in manager.namemap + assert not get('test-service-2').running signal.signal(signal.SIGCHLD, SIGCHLD_handler) - call('test-once', ('sleep', '5'), notify) + once('test-once', ('sleep', '5'), notify) assert 'test-once' not in manager.services assert 'test-once' in manager.namemap + assert get('test-once').running start('test-service') assert 'test-service' in manager.namemap + assert get('test-service').running print "Known processes:", manager.services.keys() print "Waiting...", manager.namemap.keys() @@ -271,3 +283,10 @@ if __name__ == '__main__': assert 'test-once' not in manager.services assert 'test-once' not in manager.namemap + once('test-wait', ('sleep', '2')) + print 'test-wait returned?', get('test-wait').process.poll() + assert get('test-wait').running + print 'Waiting test-wait to return...' + ret = get('test-wait').process.wait() + print 'Done! returned:', ret +