Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Side by Side Diff: tools/drmemory/scripts/common.py

Issue 1452293002: Add Dr. Memory tool (Closed) Base URL: https://pdfium.googlesource.com/pdfium.git@master
Patch Set: remove more unused code Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « tools/drmemory/DrMemory-Windows-sfx.exe ('k') | tools/drmemory/scripts/drmemory_analyze.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4
5 import logging
6 import platform
7 import os
8 import signal
9 import subprocess
10 import sys
11 import time
12
13
14 class NotImplementedError(Exception):
15 pass
16
17
18 class TimeoutError(Exception):
19 pass
20
21
22 def RunSubprocessInBackground(proc):
23 """Runs a subprocess in the background. Returns a handle to the process."""
24 logging.info("running %s in the background" % " ".join(proc))
25 return subprocess.Popen(proc)
26
27
28 def RunSubprocess(proc, timeout=0):
29 """ Runs a subprocess, until it finishes or |timeout| is exceeded and the
30 process is killed with taskkill. A |timeout| <= 0 means no timeout.
31
32 Args:
33 proc: list of process components (exe + args)
34 timeout: how long to wait before killing, <= 0 means wait forever
35 """
36
37 logging.info("running %s, timeout %d sec" % (" ".join(proc), timeout))
38 sys.stdout.flush()
39 sys.stderr.flush()
40
41 # Manually read and print out stdout and stderr.
42 # By default, the subprocess is supposed to inherit these from its parent,
43 # however when run under buildbot, it seems unable to read data from a
44 # grandchild process, so we have to read the child and print the data as if
45 # it came from us for buildbot to read it. We're not sure why this is
46 # necessary.
47 # TODO(erikkay): should we buffer stderr and stdout separately?
48 p = subprocess.Popen(proc, universal_newlines=True,
49 bufsize=0, # unbuffered
50 stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
51
52 logging.info("started subprocess")
53
54 did_timeout = False
55 if timeout > 0:
56 wait_until = time.time() + timeout
57 while p.poll() is None and not did_timeout:
58 # Have to use readline rather than readlines() or "for line in p.stdout:",
59 # otherwise we get buffered even with bufsize=0.
60 line = p.stdout.readline()
61 while line and not did_timeout:
62 sys.stdout.write(line)
63 sys.stdout.flush()
64 line = p.stdout.readline()
65 if timeout > 0:
66 did_timeout = time.time() > wait_until
67
68 if did_timeout:
69 logging.info("process timed out")
70 else:
71 logging.info("process ended, did not time out")
72
73 if did_timeout:
74 if IsWindows():
75 subprocess.call(["taskkill", "/T", "/F", "/PID", str(p.pid)])
76 else:
77 # Does this kill all children, too?
78 os.kill(p.pid, signal.SIGINT)
79 logging.error("KILLED %d" % p.pid)
80 # Give the process a chance to actually die before continuing
81 # so that cleanup can happen safely.
82 time.sleep(1.0)
83 logging.error("TIMEOUT waiting for %s" % proc[0])
84 raise TimeoutError(proc[0])
85 else:
86 for line in p.stdout:
87 sys.stdout.write(line)
88 if not IsMac(): # stdout flush fails on Mac
89 logging.info("flushing stdout")
90 sys.stdout.flush()
91
92 logging.info("collecting result code")
93 result = p.poll()
94 if result:
95 logging.error("%s exited with non-zero result code %d" % (proc[0], result))
96 return result
97
98
99 def IsLinux():
100 return sys.platform.startswith('linux')
101
102
103 def IsMac():
104 return sys.platform.startswith('darwin')
105
106
107 def IsWindows():
108 return sys.platform == 'cygwin' or sys.platform.startswith('win')
109
110
111 def WindowsVersionName():
112 """Returns the name of the Windows version if it is known, or None.
113
114 Possible return values are: xp, vista, 7, 8, or None
115 """
116 if sys.platform == 'cygwin':
117 # Windows version number is hiding in system name. Looks like:
118 # CYGWIN_NT-6.1-WOW64
119 try:
120 version_str = platform.uname()[0].split('-')[1]
121 except:
122 return None
123 elif sys.platform.startswith('win'):
124 # Normal Windows version string. Mine: 6.1.7601
125 version_str = platform.version()
126 else:
127 return None
128
129 parts = version_str.split('.')
130 try:
131 major = int(parts[0])
132 minor = int(parts[1])
133 except:
134 return None # Can't parse, unknown version.
135
136 if major == 5:
137 return 'xp'
138 elif major == 6 and minor == 0:
139 return 'vista'
140 elif major == 6 and minor == 1:
141 return '7'
142 elif major == 6 and minor == 2:
143 return '8' # Future proof. ;)
144 return None
145
146
147 def PlatformNames():
148 """Return an array of string to be used in paths for the platform
149 (e.g. suppressions, gtest filters, ignore files etc.)
150 The first element of the array describes the 'main' platform
151 """
152 if IsLinux():
153 return ['linux']
154 if IsMac():
155 return ['mac']
156 if IsWindows():
157 names = ['win32']
158 version_name = WindowsVersionName()
159 if version_name is not None:
160 names.append('win-%s' % version_name)
161 return names
162 raise NotImplementedError('Unknown platform "%s".' % sys.platform)
163
164
165 def PutEnvAndLog(env_name, env_value):
166 os.putenv(env_name, env_value)
167 logging.info('export %s=%s', env_name, env_value)
168
169 def BoringCallers(mangled, use_re_wildcards):
170 """Return a list of 'boring' function names (optinally mangled)
171 with */? wildcards (optionally .*/.).
172 Boring = we drop off the bottom of stack traces below such functions.
173 """
174
175 need_mangling = [
176 # Don't show our testing framework:
177 ("testing::Test::Run", "_ZN7testing4Test3RunEv"),
178 ("testing::TestInfo::Run", "_ZN7testing8TestInfo3RunEv"),
179 ("testing::internal::Handle*ExceptionsInMethodIfSupported*",
180 "_ZN7testing8internal3?Handle*ExceptionsInMethodIfSupported*"),
181
182 # Depend on scheduling:
183 ("MessageLoop::Run", "_ZN11MessageLoop3RunEv"),
184 ("MessageLoop::RunTask", "_ZN11MessageLoop7RunTask*"),
185 ("RunnableMethod*", "_ZN14RunnableMethod*"),
186 ("DispatchToMethod*", "_Z*16DispatchToMethod*"),
187 ("base::internal::Invoker*::DoInvoke*",
188 "_ZN4base8internal8Invoker*DoInvoke*"), # Invoker{1,2,3}
189 ("base::internal::RunnableAdapter*::Run*",
190 "_ZN4base8internal15RunnableAdapter*Run*"),
191 ]
192
193 ret = []
194 for pair in need_mangling:
195 ret.append(pair[1 if mangled else 0])
196
197 ret += [
198 # Also don't show the internals of libc/pthread.
199 "start_thread",
200 "main",
201 "BaseThreadInitThunk",
202 ]
203
204 if use_re_wildcards:
205 for i in range(0, len(ret)):
206 ret[i] = ret[i].replace('*', '.*').replace('?', '.')
207
208 return ret
209
210 def NormalizeWindowsPath(path):
211 """If we're using Cygwin Python, turn the path into a Windows path.
212
213 Don't turn forward slashes into backslashes for easier copy-pasting and
214 escaping.
215
216 TODO(rnk): If we ever want to cut out the subprocess invocation, we can use
217 _winreg to get the root Cygwin directory from the registry key:
218 HKEY_LOCAL_MACHINE\SOFTWARE\Cygwin\setup\rootdir.
219 """
220 if sys.platform.startswith("cygwin"):
221 p = subprocess.Popen(["cygpath", "-m", path],
222 stdout=subprocess.PIPE,
223 stderr=subprocess.PIPE)
224 (out, err) = p.communicate()
225 if err:
226 logging.warning("WARNING: cygpath error: %s", err)
227 return out.strip()
228 else:
229 return path
230
231 ############################
232 # Common output format code
233
234 def PrintUsedSuppressionsList(suppcounts):
235 """ Prints out the list of used suppressions in a format common to all the
236 memory tools. If the list is empty, prints nothing and returns False,
237 otherwise True.
238
239 suppcounts: a dictionary of used suppression counts,
240 Key -> name, Value -> count.
241 """
242 if not suppcounts:
243 return False
244
245 print "-----------------------------------------------------"
246 print "Suppressions used:"
247 print " count name"
248 for (name, count) in sorted(suppcounts.items(), key=lambda (k,v): (v,k)):
249 print "%7d %s" % (count, name)
250 print "-----------------------------------------------------"
251 sys.stdout.flush()
252 return True
OLDNEW
« no previous file with comments | « tools/drmemory/DrMemory-Windows-sfx.exe ('k') | tools/drmemory/scripts/drmemory_analyze.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698