|  | #!/usr/bin/env python3 | 
|  | # | 
|  | # Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file | 
|  | # for details. All rights reserved. Use of this source code is governed by a | 
|  | # BSD-style license that can be found in the LICENSE file. | 
|  |  | 
|  | # Simple wrapper for running Valgrind and checking the output on | 
|  | # stderr for memory leaks. | 
|  |  | 
|  | import subprocess | 
|  | import sys | 
|  | import re | 
|  |  | 
|  | VALGRIND_ARGUMENTS = [ | 
|  | 'valgrind', | 
|  | '--error-exitcode=1', | 
|  | '--leak-check=full', | 
|  | '--trace-children=yes', | 
|  | '--ignore-ranges=0x000-0xFFF',  # Used for implicit null checks. | 
|  | '--vex-iropt-level=1'  # Valgrind crashes with the default level (2). | 
|  | ] | 
|  |  | 
|  | # Compute the command line. | 
|  | command = VALGRIND_ARGUMENTS + sys.argv[1:] | 
|  |  | 
|  | # Run Valgrind. | 
|  | process = subprocess.Popen( | 
|  | command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) | 
|  | code = process.wait() | 
|  | output = process.stdout.readlines() | 
|  | errors = process.stderr.readlines() | 
|  |  | 
|  | # Always print the output, but leave out the 3 line banner printed | 
|  | # by certain versions of Valgrind. | 
|  | if len(output) > 0 and output[0].startswith("** VALGRIND_ROOT="): | 
|  | output = output[3:] | 
|  | sys.stdout.writelines(output) | 
|  |  | 
|  | # If Valgrind produced an error, we report that to the user. | 
|  | if code != 0: | 
|  | sys.stderr.writelines(errors) | 
|  | sys.exit(code) | 
|  |  | 
|  | # Look through the leak details and make sure that we don't have | 
|  | # any definitely or indirectly lost bytes. We allow possibly lost | 
|  | # bytes to lower the risk of false positives. | 
|  | LEAK_RE = r"(?:definitely|indirectly) lost:" | 
|  | LEAK_LINE_MATCHER = re.compile(LEAK_RE) | 
|  | LEAK_OKAY_MATCHER = re.compile(r"lost: 0 bytes in 0 blocks") | 
|  | leaks = [] | 
|  | for line in errors: | 
|  | if LEAK_LINE_MATCHER.search(line): | 
|  | leaks.append(line) | 
|  | if not LEAK_OKAY_MATCHER.search(line): | 
|  | sys.stderr.writelines(errors) | 
|  | sys.exit(1) | 
|  |  | 
|  | # Make sure we found the right number of leak lines. | 
|  | if not len(leaks) in [0, 2, 3]: | 
|  | sys.stderr.writelines(errors) | 
|  | sys.stderr.write('\n\n#### Malformed Valgrind output.\n#### Exiting.\n') | 
|  | sys.exit(1) | 
|  |  | 
|  | # Success. | 
|  | sys.exit(0) |