diff options
author | maruel@chromium.org <maruel@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-11-23 20:02:40 +0000 |
---|---|---|
committer | maruel@chromium.org <maruel@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-11-23 20:02:40 +0000 |
commit | cc8f2810b5a7dfeb7d4310f50be9f527056aa313 (patch) | |
tree | 91891545bf03238d4d407bf8ec4db9860eb99458 /tools/valgrind/common.py | |
parent | 6780b3bd5805018c242cde0a9cff3f48d12e4649 (diff) | |
download | chromium_src-cc8f2810b5a7dfeb7d4310f50be9f527056aa313.zip chromium_src-cc8f2810b5a7dfeb7d4310f50be9f527056aa313.tar.gz chromium_src-cc8f2810b5a7dfeb7d4310f50be9f527056aa313.tar.bz2 |
Fix valgrind run.
TEST=valgrind works
BUG=none
Review URL: http://codereview.chromium.org/437014
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@32836 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'tools/valgrind/common.py')
-rwxr-xr-x | tools/valgrind/common.py | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/tools/valgrind/common.py b/tools/valgrind/common.py new file mode 100755 index 0000000..d273bf7 --- /dev/null +++ b/tools/valgrind/common.py @@ -0,0 +1,112 @@ +# Copyright (c) 2009 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 os +import signal +import subprocess +import sys +import time + + +class TimeoutError(Exception): + pass + + +def _print_line(line, flush=True): + # Printing to a text file (including stdout) on Windows always winds up + # using \r\n automatically. On buildbot, this winds up being read by a master + # running on Linux, so we manually convert crlf to '\n' + print line.rstrip() + '\n', + if flush: + sys.stdout.flush() + + +def RunSubprocess(proc, timeout=0, detach=False): + """ 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 + detach: Whether to pass the DETACHED_PROCESS argument to CreateProcess + on Windows. This is used by Purify subprocesses on buildbot which + seem to get confused by the parent console that buildbot sets up. + """ + + logging.info("running %s, timeout %d sec" % (" ".join(proc), timeout)) + if detach: + # see MSDN docs for "Process Creation Flags" + DETACHED_PROCESS = 0x8 + p = subprocess.Popen(proc, creationflags=DETACHED_PROCESS) + else: + # For non-detached processes, 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, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + + logging.info("started subprocess") + + # How long to wait (in seconds) before printing progress log messages. + progress_delay = 300 + progress_delay_time = time.time() + progress_delay + did_timeout = False + if timeout > 0: + wait_until = time.time() + timeout + while p.poll() is None and not did_timeout: + if not detach: + line = p.stdout.readline() + while line and not did_timeout: + _print_line(line) + line = p.stdout.readline() + if timeout > 0: + did_timeout = time.time() > wait_until + else: + # When we detach, blocking on reading stdout doesn't work, so we sleep + # a short time and poll. + time.sleep(0.5) + if time.time() >= progress_delay_time: + # Force output on a periodic basis to avoid getting killed off by the + # buildbot. + # TODO(erikkay): I'd prefer a less obtrusive 'print ".",' with a flush + # but because of how we're doing subprocesses, this doesn't appear to + # work reliably. + logging.info("%s still running..." % os.path.basename(proc[0])) + progress_delay_time = time.time() + progress_delay + 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 sys.platform == "win32": + 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]) + elif not detach: + for line in p.stdout.readlines(): + _print_line(line, False) + if sys.platform != 'darwin': # stdout flush fails on Mac + logging.info("flushing stdout") + p.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 |