diff options
Diffstat (limited to 'tools/drmemory/scripts/common.py')
-rw-r--r-- | tools/drmemory/scripts/common.py | 252 |
1 files changed, 0 insertions, 252 deletions
diff --git a/tools/drmemory/scripts/common.py b/tools/drmemory/scripts/common.py deleted file mode 100644 index 7e163e3c60..0000000000 --- a/tools/drmemory/scripts/common.py +++ /dev/null @@ -1,252 +0,0 @@ -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import logging -import platform -import os -import signal -import subprocess -import sys -import time - - -class NotImplementedError(Exception): - pass - - -class TimeoutError(Exception): - pass - - -def RunSubprocessInBackground(proc): - """Runs a subprocess in the background. Returns a handle to the process.""" - logging.info("running %s in the background" % " ".join(proc)) - return subprocess.Popen(proc) - - -def RunSubprocess(proc, timeout=0): - """ Runs a subprocess, until it finishes or |timeout| is exceeded and the - process is killed with taskkill. A |timeout| <= 0 means no timeout. - - Args: - proc: list of process components (exe + args) - timeout: how long to wait before killing, <= 0 means wait forever - """ - - logging.info("running %s, timeout %d sec" % (" ".join(proc), timeout)) - sys.stdout.flush() - sys.stderr.flush() - - # Manually read and print out stdout and stderr. - # By default, the subprocess is supposed to inherit these from its parent, - # however when run under buildbot, it seems unable to read data from a - # grandchild process, so we have to read the child and print the data as if - # it came from us for buildbot to read it. We're not sure why this is - # necessary. - # TODO(erikkay): should we buffer stderr and stdout separately? - p = subprocess.Popen(proc, universal_newlines=True, - bufsize=0, # unbuffered - stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - - logging.info("started subprocess") - - did_timeout = False - if timeout > 0: - wait_until = time.time() + timeout - while p.poll() is None and not did_timeout: - # Have to use readline rather than readlines() or "for line in p.stdout:", - # otherwise we get buffered even with bufsize=0. - line = p.stdout.readline() - while line and not did_timeout: - sys.stdout.write(line) - sys.stdout.flush() - line = p.stdout.readline() - if timeout > 0: - did_timeout = time.time() > wait_until - - if did_timeout: - logging.info("process timed out") - else: - logging.info("process ended, did not time out") - - if did_timeout: - if IsWindows(): - subprocess.call(["taskkill", "/T", "/F", "/PID", str(p.pid)]) - else: - # Does this kill all children, too? - os.kill(p.pid, signal.SIGINT) - logging.error("KILLED %d" % p.pid) - # Give the process a chance to actually die before continuing - # so that cleanup can happen safely. - time.sleep(1.0) - logging.error("TIMEOUT waiting for %s" % proc[0]) - raise TimeoutError(proc[0]) - else: - for line in p.stdout: - sys.stdout.write(line) - if not IsMac(): # stdout flush fails on Mac - logging.info("flushing stdout") - sys.stdout.flush() - - logging.info("collecting result code") - result = p.poll() - if result: - logging.error("%s exited with non-zero result code %d" % (proc[0], result)) - return result - - -def IsLinux(): - return sys.platform.startswith('linux') - - -def IsMac(): - return sys.platform.startswith('darwin') - - -def IsWindows(): - return sys.platform == 'cygwin' or sys.platform.startswith('win') - - -def WindowsVersionName(): - """Returns the name of the Windows version if it is known, or None. - - Possible return values are: xp, vista, 7, 8, or None - """ - if sys.platform == 'cygwin': - # Windows version number is hiding in system name. Looks like: - # CYGWIN_NT-6.1-WOW64 - try: - version_str = platform.uname()[0].split('-')[1] - except: - return None - elif sys.platform.startswith('win'): - # Normal Windows version string. Mine: 6.1.7601 - version_str = platform.version() - else: - return None - - parts = version_str.split('.') - try: - major = int(parts[0]) - minor = int(parts[1]) - except: - return None # Can't parse, unknown version. - - if major == 5: - return 'xp' - elif major == 6 and minor == 0: - return 'vista' - elif major == 6 and minor == 1: - return '7' - elif major == 6 and minor == 2: - return '8' # Future proof. ;) - return None - - -def PlatformNames(): - """Return an array of string to be used in paths for the platform - (e.g. suppressions, gtest filters, ignore files etc.) - The first element of the array describes the 'main' platform - """ - if IsLinux(): - return ['linux'] - if IsMac(): - return ['mac'] - if IsWindows(): - names = ['win32'] - version_name = WindowsVersionName() - if version_name is not None: - names.append('win-%s' % version_name) - return names - raise NotImplementedError('Unknown platform "%s".' % sys.platform) - - -def PutEnvAndLog(env_name, env_value): - os.putenv(env_name, env_value) - logging.info('export %s=%s', env_name, env_value) - -def BoringCallers(mangled, use_re_wildcards): - """Return a list of 'boring' function names (optinally mangled) - with */? wildcards (optionally .*/.). - Boring = we drop off the bottom of stack traces below such functions. - """ - - need_mangling = [ - # Don't show our testing framework: - ("testing::Test::Run", "_ZN7testing4Test3RunEv"), - ("testing::TestInfo::Run", "_ZN7testing8TestInfo3RunEv"), - ("testing::internal::Handle*ExceptionsInMethodIfSupported*", - "_ZN7testing8internal3?Handle*ExceptionsInMethodIfSupported*"), - - # Depend on scheduling: - ("MessageLoop::Run", "_ZN11MessageLoop3RunEv"), - ("MessageLoop::RunTask", "_ZN11MessageLoop7RunTask*"), - ("RunnableMethod*", "_ZN14RunnableMethod*"), - ("DispatchToMethod*", "_Z*16DispatchToMethod*"), - ("base::internal::Invoker*::DoInvoke*", - "_ZN4base8internal8Invoker*DoInvoke*"), # Invoker{1,2,3} - ("base::internal::RunnableAdapter*::Run*", - "_ZN4base8internal15RunnableAdapter*Run*"), - ] - - ret = [] - for pair in need_mangling: - ret.append(pair[1 if mangled else 0]) - - ret += [ - # Also don't show the internals of libc/pthread. - "start_thread", - "main", - "BaseThreadInitThunk", - ] - - if use_re_wildcards: - for i in range(0, len(ret)): - ret[i] = ret[i].replace('*', '.*').replace('?', '.') - - return ret - -def NormalizeWindowsPath(path): - """If we're using Cygwin Python, turn the path into a Windows path. - - Don't turn forward slashes into backslashes for easier copy-pasting and - escaping. - - TODO(rnk): If we ever want to cut out the subprocess invocation, we can use - _winreg to get the root Cygwin directory from the registry key: - HKEY_LOCAL_MACHINE\SOFTWARE\Cygwin\setup\rootdir. - """ - if sys.platform.startswith("cygwin"): - p = subprocess.Popen(["cygpath", "-m", path], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - (out, err) = p.communicate() - if err: - logging.warning("WARNING: cygpath error: %s", err) - return out.strip() - else: - return path - -############################ -# Common output format code - -def PrintUsedSuppressionsList(suppcounts): - """ Prints out the list of used suppressions in a format common to all the - memory tools. If the list is empty, prints nothing and returns False, - otherwise True. - - suppcounts: a dictionary of used suppression counts, - Key -> name, Value -> count. - """ - if not suppcounts: - return False - - print "-----------------------------------------------------" - print "Suppressions used:" - print " count name" - for (name, count) in sorted(suppcounts.items(), key=lambda (k,v): (v,k)): - print "%7d %s" % (count, name) - print "-----------------------------------------------------" - sys.stdout.flush() - return True |