1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 """
18
19 This module provides bits and pieces to implement generic Task proxy
20 objects.
21
22 """
23
24
25 import fcntl, os, pty, select, signal
26
30
31 - def spawn(self, path, args, env=None):
32 """Start the task."""
33
34 (pid, tid) = pty.fork()
35 if pid == 0:
36 try:
37 if env:
38 os.execve(path, args, env)
39 else:
40 os.execv(path, args)
41 finally:
42 os._exit(1)
43 else:
44 fcntl.fcntl(tid, fcntl.F_SETFL, os.O_NONBLOCK)
45 self._pid[tid] = pid
46 return tid
47
49 """Check whether the task has finished."""
50 return self._pid[tid] == 0
51
53 """Return task's messages."""
54
55 (iwtd, owtd, ewtd) = select.select([tid], [], [], 0.25)
56 if tid in iwtd:
57 try:
58 messages = os.read(tid, 1024)
59 if len(messages) > 0:
60 messages = messages.split('\r\n')
61 return [msg for msg in messages if msg]
62 except:
63 pass
64
65 pass
66
67
68
69 (pid, status) = os.waitpid(self._pid[tid], os.WNOHANG)
70 if pid:
71 assert(pid == self._pid[tid])
72 if os.WIFEXITED(status) or os.WIFSIGNALED(status):
73 self._pid[tid] = 0
74 return []
75
76 - def feed(self, tid, banana):
77 """Feed the task."""
78
79 os.write(tid, banana)
80 pass
81
82 - def wait(self, tid):
83 """Wait for the task to finish."""
84
85 assert(self.finished(tid))
86
87 del self._pid[tid]
88 os.close(tid)
89 return
90
91 - def abort(self, tid, sig=signal.SIGINT):
92 """Abort a task."""
93
94 os.kill (self._pid[tid], sig)
95
96 del self._pid[tid]
97 os.close(tid)
98 return
99