1
2
3
4
5
6
7
8
9
10
11 import os
12 import time
13 import errno
14
15 from .exceptions import TimeoutExpiredError
16
17
18
19
20
21
23
24 def is_exe(fpath):
25 return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
26
27 fpath, unused_fname = os.path.split(program)
28 if fpath:
29 if is_exe(program):
30 return program
31 else:
32 for path in os.environ["PATH"].split(os.pathsep):
33 path = path.strip('"')
34 exe_file = os.path.join(path, program)
35 if is_exe(exe_file):
36 return exe_file
37
38 return None
39
40
41
42
43
44
45
47 """Check whether pid exists in the current process table."""
48 if pid < 0:
49 return False
50 try:
51 os.kill(pid, 0)
52 except OSError, e:
53 return e.errno == errno.EPERM
54 else:
55 return True
56
57
59 """Wait for process with pid 'pid' to terminate and return its
60 exit status code as an integer.
61
62 If pid is not a children of os.getpid() (current process) just
63 waits until the process disappears and return None.
64
65 If pid does not exist at all return None immediately.
66
67 Raise TimeoutExpiredError on timeout expired (if specified).
68 """
69 def check_timeout(delay):
70 if timeout is not None:
71 if time.time() >= stop_at:
72 raise TimeoutExpiredError
73 time.sleep(delay)
74 return min(delay * 2, 0.04)
75
76 if timeout is not None:
77 waitcall = lambda: os.waitpid(pid, os.WNOHANG)
78 stop_at = time.time() + timeout
79 else:
80 waitcall = lambda: os.waitpid(pid, 0)
81
82 delay = 0.0001
83 while 1:
84 try:
85 retpid, status = waitcall()
86 except OSError, err:
87 if err.errno == errno.EINTR:
88 delay = check_timeout(delay)
89 continue
90 elif err.errno == errno.ECHILD:
91
92
93
94
95
96
97 while 1:
98 if pid_exists(pid):
99 delay = check_timeout(delay)
100 else:
101 return
102 else:
103 raise
104 else:
105 if retpid == 0:
106
107 delay = check_timeout(delay)
108 continue
109
110
111 if os.WIFSIGNALED(status):
112 return os.WTERMSIG(status)
113
114
115 elif os.WIFEXITED(status):
116 return os.WEXITSTATUS(status)
117 else:
118
119 raise RuntimeError("unknown process exit status")
120