]> git.llucax.com Git - software/pymin.git/commitdiff
Add a ProcessManager class to manage processes.
authorLeandro Lucarella <llucax@gmail.com>
Mon, 12 Nov 2007 17:00:26 +0000 (14:00 -0300)
committerLeandro Lucarella <llucax@gmail.com>
Mon, 12 Nov 2007 17:00:26 +0000 (14:00 -0300)
pymin/procman.py [new file with mode: 0644]

diff --git a/pymin/procman.py b/pymin/procman.py
new file mode 100644 (file)
index 0000000..423ace0
--- /dev/null
@@ -0,0 +1,98 @@
+# vim: set encoding=utf-8 et sw=4 sts=4 :
+
+import os
+import errno
+import subprocess
+
+class ProcessInfo:
+    def __init__(self, name, process, args, kw, callback=None, persist=False):
+        self.name = name
+        self.process = process
+        self.args = args
+        self.kw = kw
+        self.callback = callback
+        self.persist = persist
+    def __repr__(self):
+        return 'ProcessInfo(name=%s, pid=%s, persist=%s, cb=%s, args=%s)' % (
+                    self.name, self.process.pid, self.persist,
+                    self.callback.__name__, self.args)
+
+class ProcessManager:
+
+    def __init__(self):
+        self.namemap = dict()
+        self.pidmap = dict()
+
+    def call(self, name, callback, persist, *args, **kw):
+        proc = subprocess.Popen(*args, **kw)
+        procinfo = ProcessInfo(name, proc, args, kw, callback, persist)
+        self.namemap[name] = self.pidmap[proc.pid] = procinfo
+
+    def sigchild_handler(self, signum):
+        try:
+            (pid, status) = os.waitpid(-1, os.WNOHANG)
+        except OSError, e:
+            if e.errno is e.ECHILD:
+                return
+            raise
+        while pid:
+            if pid in self.pidmap:
+                p = self.pidmap[pid]
+                del self.namemap[p.name]
+                del self.pidmap[pid]
+                if p.callback is not None:
+                    p.callback(p)
+                if p.persist:
+                    self.call(p.name, p.callback, True, *p.args, **p.kw)
+            try:
+                (pid, status) = os.waitpid(-1, os.WNOHANG)
+            except OSError, e:
+                if e.errno == errno.ECHILD:
+                    return
+                raise
+
+    def __getitem__(self, name):
+        if isinstance(name, basestring): # is a name
+            return self.namemap[name]
+        else: # is a pid
+            return self.pidmap[name]
+
+    def __contains__(self, name):
+        if isinstance(name, basestring): # is a name
+            return name in self.namemap
+        else: # is a pid
+            return name in self.pidmap
+
+
+if __name__ == '__main__':
+
+    import signal
+    import time
+
+    sig = None
+
+    def sigchild_handler(signum, stacktrace):
+        global sig
+        sig = signum
+        print 'SIGCHLD', signum
+
+    def test_notify(proc):
+        print 'test died:', proc, proc.name, proc.process.pid
+
+    procman = ProcessManager()
+
+    signal.signal(signal.SIGCHLD, sigchild_handler)
+
+    procman.call('test', test_notify, True, ('sleep', '5'))
+
+    while True:
+        time.sleep(1)
+        print "Esperando...",
+        if 'test' in procman:
+            print procman['test']
+        else:
+            print
+        if sig == signal.SIGCHLD:
+            sig = None
+            procman.sigchild_handler(sig)
+