Thu, 15 Jan 2015 21:13:52 +0100
Remove forgotten relic of ABI crash risk averse overloaded method change.
1 #!/usr/bin/env python
3 # Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file.
7 """Routines common to all posix systems."""
9 import os
10 import errno
11 import psutil
12 import sys
13 import time
14 import glob
16 from psutil._error import TimeoutExpired
17 from psutil._common import nt_diskinfo, usage_percent, memoize
20 def pid_exists(pid):
21 """Check whether pid exists in the current process table."""
22 if pid < 0:
23 return False
24 try:
25 os.kill(pid, 0)
26 except OSError:
27 e = sys.exc_info()[1]
28 return e.errno == errno.EPERM
29 else:
30 return True
32 def wait_pid(pid, timeout=None):
33 """Wait for process with pid 'pid' to terminate and return its
34 exit status code as an integer.
36 If pid is not a children of os.getpid() (current process) just
37 waits until the process disappears and return None.
39 If pid does not exist at all return None immediately.
41 Raise TimeoutExpired on timeout expired.
42 """
43 def check_timeout(delay):
44 if timeout is not None:
45 if timer() >= stop_at:
46 raise TimeoutExpired(pid)
47 time.sleep(delay)
48 return min(delay * 2, 0.04)
50 timer = getattr(time, 'monotonic', time.time)
51 if timeout is not None:
52 waitcall = lambda: os.waitpid(pid, os.WNOHANG)
53 stop_at = timer() + timeout
54 else:
55 waitcall = lambda: os.waitpid(pid, 0)
57 delay = 0.0001
58 while 1:
59 try:
60 retpid, status = waitcall()
61 except OSError:
62 err = sys.exc_info()[1]
63 if err.errno == errno.EINTR:
64 delay = check_timeout(delay)
65 continue
66 elif err.errno == errno.ECHILD:
67 # This has two meanings:
68 # - pid is not a child of os.getpid() in which case
69 # we keep polling until it's gone
70 # - pid never existed in the first place
71 # In both cases we'll eventually return None as we
72 # can't determine its exit status code.
73 while 1:
74 if pid_exists(pid):
75 delay = check_timeout(delay)
76 else:
77 return
78 else:
79 raise
80 else:
81 if retpid == 0:
82 # WNOHANG was used, pid is still running
83 delay = check_timeout(delay)
84 continue
85 # process exited due to a signal; return the integer of
86 # that signal
87 if os.WIFSIGNALED(status):
88 return os.WTERMSIG(status)
89 # process exited using exit(2) system call; return the
90 # integer exit(2) system call has been called with
91 elif os.WIFEXITED(status):
92 return os.WEXITSTATUS(status)
93 else:
94 # should never happen
95 raise RuntimeError("unknown process exit status")
97 def get_disk_usage(path):
98 """Return disk usage associated with path."""
99 st = os.statvfs(path)
100 free = (st.f_bavail * st.f_frsize)
101 total = (st.f_blocks * st.f_frsize)
102 used = (st.f_blocks - st.f_bfree) * st.f_frsize
103 percent = usage_percent(used, total, _round=1)
104 # NB: the percentage is -5% than what shown by df due to
105 # reserved blocks that we are currently not considering:
106 # http://goo.gl/sWGbH
107 return nt_diskinfo(total, used, free, percent)
109 @memoize
110 def _get_terminal_map():
111 ret = {}
112 ls = glob.glob('/dev/tty*') + glob.glob('/dev/pts/*')
113 for name in ls:
114 assert name not in ret
115 try:
116 ret[os.stat(name).st_rdev] = name
117 except OSError:
118 err = sys.exc_info()[1]
119 if err.errno != errno.ENOENT:
120 raise
121 return ret