]> git.llucax.com Git - software/pymin.git/blob - pymin/procman.py
Add a ProcessManager class to manage processes.
[software/pymin.git] / pymin / procman.py
1 # vim: set encoding=utf-8 et sw=4 sts=4 :
2
3 import os
4 import errno
5 import subprocess
6
7 class ProcessInfo:
8     def __init__(self, name, process, args, kw, callback=None, persist=False):
9         self.name = name
10         self.process = process
11         self.args = args
12         self.kw = kw
13         self.callback = callback
14         self.persist = persist
15     def __repr__(self):
16         return 'ProcessInfo(name=%s, pid=%s, persist=%s, cb=%s, args=%s)' % (
17                     self.name, self.process.pid, self.persist,
18                     self.callback.__name__, self.args)
19
20 class ProcessManager:
21
22     def __init__(self):
23         self.namemap = dict()
24         self.pidmap = dict()
25
26     def call(self, name, callback, persist, *args, **kw):
27         proc = subprocess.Popen(*args, **kw)
28         procinfo = ProcessInfo(name, proc, args, kw, callback, persist)
29         self.namemap[name] = self.pidmap[proc.pid] = procinfo
30
31     def sigchild_handler(self, signum):
32         try:
33             (pid, status) = os.waitpid(-1, os.WNOHANG)
34         except OSError, e:
35             if e.errno is e.ECHILD:
36                 return
37             raise
38         while pid:
39             if pid in self.pidmap:
40                 p = self.pidmap[pid]
41                 del self.namemap[p.name]
42                 del self.pidmap[pid]
43                 if p.callback is not None:
44                     p.callback(p)
45                 if p.persist:
46                     self.call(p.name, p.callback, True, *p.args, **p.kw)
47             try:
48                 (pid, status) = os.waitpid(-1, os.WNOHANG)
49             except OSError, e:
50                 if e.errno == errno.ECHILD:
51                     return
52                 raise
53
54     def __getitem__(self, name):
55         if isinstance(name, basestring): # is a name
56             return self.namemap[name]
57         else: # is a pid
58             return self.pidmap[name]
59
60     def __contains__(self, name):
61         if isinstance(name, basestring): # is a name
62             return name in self.namemap
63         else: # is a pid
64             return name in self.pidmap
65
66
67 if __name__ == '__main__':
68
69     import signal
70     import time
71
72     sig = None
73
74     def sigchild_handler(signum, stacktrace):
75         global sig
76         sig = signum
77         print 'SIGCHLD', signum
78
79     def test_notify(proc):
80         print 'test died:', proc, proc.name, proc.process.pid
81
82     procman = ProcessManager()
83
84     signal.signal(signal.SIGCHLD, sigchild_handler)
85
86     procman.call('test', test_notify, True, ('sleep', '5'))
87
88     while True:
89         time.sleep(1)
90         print "Esperando...",
91         if 'test' in procman:
92             print procman['test']
93         else:
94             print
95         if sig == signal.SIGCHLD:
96             sig = None
97             procman.sigchild_handler(sig)
98