author | Wes Kocher <wkocher@mozilla.com> |
Tue, 22 Sep 2015 17:08:37 -0700 | |
changeset 263821 | 19b4265d0d568d232fb3a34705f947b6db7496dc |
parent 263820 | 05a7ee49d40a4cfabf2479337fd5e1312e178b6d |
child 263832 | 709aa64305d1378b3f92a34f998bbbfff62cd1d9 |
child 263847 | 3450ce49c7d74dcee0b9272a62d0e861b44b2a46 |
child 263908 | a39e05b423f34e8546a82f702bd48975af082e81 |
push id | 29419 |
push user | kwierso@gmail.com |
push date | Wed, 23 Sep 2015 00:08:39 +0000 |
treeherder | mozilla-central@19b4265d0d56 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | backout |
bugs | 1185244 |
milestone | 44.0a1 |
backs out | feceb41f1c3c66031164d5db8701c208f571a9b1 |
first release with | nightly linux32
19b4265d0d56
/
44.0a1
/
20150923030230
/
files
nightly linux64
19b4265d0d56
/
44.0a1
/
20150923030230
/
files
nightly mac
19b4265d0d56
/
44.0a1
/
20150923030230
/
files
nightly win32
19b4265d0d56
/
44.0a1
/
20150923030230
/
files
nightly win64
19b4265d0d56
/
44.0a1
/
20150923030230
/
files
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
releases | nightly linux32
44.0a1
/
20150923030230
/
pushlog to previous
nightly linux64
44.0a1
/
20150923030230
/
pushlog to previous
nightly mac
44.0a1
/
20150923030230
/
pushlog to previous
nightly win32
44.0a1
/
20150923030230
/
pushlog to previous
nightly win64
44.0a1
/
20150923030230
/
pushlog to previous
|
--- a/build/automation.py.in +++ b/build/automation.py.in @@ -524,18 +524,17 @@ class Automation(object): def checkForCrashes(self, minidumpDir, symbolsPath): return mozcrash.check_for_crashes(minidumpDir, symbolsPath, test_name=self.lastTestSeen) def runApp(self, testURL, env, app, profileDir, extraArgs, utilityPath = None, xrePath = None, certPath = None, debuggerInfo = None, symbolsPath = None, timeout = -1, maxTime = None, onLaunch = None, - detectShutdownLeaks = False, screenshotOnFail=False, testPath=None, bisectChunk=None, - valgrindPath=None, valgrindArgs=None, valgrindSuppFiles=None): + detectShutdownLeaks = False, screenshotOnFail=False, testPath=None, bisectChunk=None): """ Run the app, log the duration it took to execute, return the status code. Kills the app if it runs for longer than |maxTime| seconds, or outputs nothing for |timeout| seconds. """ if utilityPath == None: utilityPath = self.DIST_BIN if xrePath == None:
--- a/layout/tools/reftest/remotereftest.py +++ b/layout/tools/reftest/remotereftest.py @@ -305,18 +305,17 @@ class RemoteReftest(RefTest): browserEnv = RefTest.buildBrowserEnv(self, options, profileDir) # remove desktop environment not used on device if "XPCOM_MEM_BLOAT_LOG" in browserEnv: del browserEnv["XPCOM_MEM_BLOAT_LOG"] return browserEnv def runApp(self, profile, binary, cmdargs, env, timeout=None, debuggerInfo=None, - symbolsPath=None, options=None, - valgrindPath=None, valgrindArgs=None, valgrindSuppFiles=None): + symbolsPath=None, options=None): status = self.automation.runApp(None, env, binary, profile.profile, cmdargs, utilityPath=options.utilityPath, xrePath=options.xrePath, debuggerInfo=debuggerInfo, symbolsPath=symbolsPath,
--- a/layout/tools/reftest/runreftest.py +++ b/layout/tools/reftest/runreftest.py @@ -580,18 +580,17 @@ class RefTest(object): return line def log(self, line): log.info(line) return line def runApp(self, profile, binary, cmdargs, env, timeout=None, debuggerInfo=None, - symbolsPath=None, options=None, - valgrindPath=None, valgrindArgs=None, valgrindSuppFiles=None): + symbolsPath=None, options=None): def timeoutHandler(): self.handleTimeout( timeout, proc, options.utilityPath, debuggerInfo) interactive = False debug_args = None if debuggerInfo:
--- a/layout/tools/reftest/runreftestb2g.py +++ b/layout/tools/reftest/runreftestb2g.py @@ -306,18 +306,17 @@ class B2GRemoteReftest(RefTest): print "Automation Error: Failed to copy extra files to device" raise def environment(self, **kwargs): return self.automation.environment(**kwargs) def runApp(self, profile, binary, cmdargs, env, timeout=None, debuggerInfo=None, - symbolsPath=None, options=None, - valgrindPath=None, valgrindArgs=None, valgrindSuppFiles=None): + symbolsPath=None, options=None): status = self.automation.runApp(None, env, binary, profile.profile, cmdargs, utilityPath=options.utilityPath, xrePath=options.xrePath, debuggerInfo=debuggerInfo, symbolsPath=symbolsPath,
--- a/testing/mochitest/mochitest_options.py +++ b/testing/mochitest/mochitest_options.py @@ -25,36 +25,16 @@ try: MachCommandConditions as conditions, ) build_obj = MozbuildObject.from_environment(cwd=here) except ImportError: build_obj = None conditions = None -def get_default_valgrind_suppression_files(): - # We are trying to locate files in the source tree. So if we - # don't know where the source tree is, we must give up. - if build_obj is None or build_obj.topsrcdir is None: - return [] - - supps_path = os.path.join(build_obj.topsrcdir, "build", "valgrind") - - rv = [] - if mozinfo.os == "linux": - if mozinfo.processor == "x86_64": - rv.append(os.path.join(supps_path, "x86_64-redhat-linux-gnu.sup")) - rv.append(os.path.join(supps_path, "cross-architecture.sup")) - elif mozinfo.processor == "x86": - rv.append(os.path.join(supps_path, "i386-redhat-linux-gnu.sup")) - rv.append(os.path.join(supps_path, "cross-architecture.sup")) - - return rv - - class ArgumentContainer(): __metaclass__ = ABCMeta @abstractproperty def args(self): pass @abstractproperty @@ -490,30 +470,16 @@ class MochitestArguments(ArgumentContain {"default": None, "help": "Debugger binary to run tests in. Program name or path.", }], [["--debugger-args"], {"dest": "debuggerArgs", "default": None, "help": "Arguments to pass to the debugger.", }], - [["--valgrind"], - {"default": None, - "help": "Valgrind binary to run tests with. Program name or path.", - }], - [["--valgrind-args"], - {"dest": "valgrindArgs", - "default": None, - "help": "Extra arguments to pass to Valgrind.", - }], - [["--valgrind-supp-files"], - {"dest": "valgrindSuppFiles", - "default": ",".join(get_default_valgrind_suppression_files()), - "help": "Comma-separated list of suppression files to pass to Valgrind.", - }], [["--debugger-interactive"], {"action": "store_true", "dest": "debuggerInteractive", "default": None, "help": "Prevents the test harness from redirecting stdout and stderr for " "interactive debuggers.", "suppress": True, }],
--- a/testing/mochitest/runtests.py +++ b/testing/mochitest/runtests.py @@ -1626,72 +1626,42 @@ class Mochitest(MochitestUtilsMixin): def runApp(self, testUrl, env, app, profile, extraArgs, utilityPath, debuggerInfo=None, - valgrindPath=None, - valgrindArgs=None, - valgrindSuppFiles=None, symbolsPath=None, timeout=-1, onLaunch=None, detectShutdownLeaks=False, screenshotOnFail=False, bisectChunk=None, quiet=False): """ Run the app, log the duration it took to execute, return the status code. Kills the app if it runs for longer than |maxTime| seconds, or outputs nothing for |timeout| seconds. """ # configure the message logger buffering self.message_logger.buffering = quiet - # It can't be the case that both a with-debugger and an - # on-Valgrind run have been requested. doTests() should have - # already excluded this possibility. - assert not(valgrindPath and debuggerInfo) - # debugger information interactive = False debug_args = None if debuggerInfo: interactive = debuggerInfo.interactive debug_args = [debuggerInfo.path] + debuggerInfo.args - # Set up Valgrind arguments. - if valgrindPath: - interactive = False - valgrindArgs_split = ([] if valgrindArgs is None - else valgrindArgs.split()) - valgrindSuppFiles_split = ([] if valgrindSuppFiles is None - else valgrindSuppFiles.split(",")) - - valgrindSuppFiles_final = [] - if valgrindSuppFiles is not None: - valgrindSuppFiles_final = ["--suppressions=" + path for path in valgrindSuppFiles.split(",")] - - debug_args = ([valgrindPath] - + mozdebug.get_default_valgrind_args() - + valgrindArgs_split - + valgrindSuppFiles_final) - # fix default timeout if timeout == -1: timeout = self.DEFAULT_TIMEOUT - # Note in the log if running on Valgrind - if valgrindPath: - self.log.info("runtests.py | Running on Valgrind. " - + "Using timeout of %d seconds." % timeout) - # copy env so we don't munge the caller's environment env = env.copy() # make sure we clean up after ourselves. try: # set process log environment variable tmpfd, processLog = tempfile.mkstemp(suffix='pidlog') os.close(tmpfd) @@ -2150,36 +2120,16 @@ class Mochitest(MochitestUtilsMixin): if options.useTestMediaDevices: devices = findTestMediaDevices(self.log) if not devices: self.log.error("Could not find test media devices to use") return 1 self.mediaDevices = devices - # See if we were asked to run on Valgrind - valgrindPath = None - valgrindArgs = None - valgrindSuppFiles = None - if options.valgrind: - valgrindPath = options.valgrind - if options.valgrindArgs: - valgrindArgs = options.valgrindArgs - if options.valgrindSuppFiles: - valgrindSuppFiles = options.valgrindSuppFiles - - if (valgrindArgs or valgrindSuppFiles) and not valgrindPath: - self.log.error("Specified --valgrind-args or --valgrind-supp-files," - " but not --valgrind") - return 1 - - if valgrindPath and debuggerInfo: - self.log.error("Can't use both --debugger and --valgrind together") - return 1 - # buildProfile sets self.profile . # This relies on sideeffects and isn't very stateful: # https://bugzilla.mozilla.org/show_bug.cgi?id=919300 self.manifest = self.buildProfile(options) if self.manifest is None: return 1 self.leak_report_file = os.path.join( @@ -2268,19 +2218,16 @@ class Mochitest(MochitestUtilsMixin): try: status = self.runApp(testURL, self.browserEnv, options.app, profile=self.profile, extraArgs=options.browserArgs, utilityPath=options.utilityPath, debuggerInfo=debuggerInfo, - valgrindPath=valgrindPath, - valgrindArgs=valgrindArgs, - valgrindSuppFiles=valgrindSuppFiles, symbolsPath=options.symbolsPath, timeout=timeout, onLaunch=onLaunch, detectShutdownLeaks=detectShutdownLeaks, screenshotOnFail=options.screenshotOnFail, bisectChunk=options.bisectChunk, quiet=options.quiet ) @@ -2566,18 +2513,17 @@ class Mochitest(MochitestUtilsMixin): if rootdir not in dirlist: dirlist.append(rootdir) return dirlist def run_test_harness(options): logger_options = { - key: value for key, value in vars(options).iteritems() - if key.startswith('log') or key == 'valgrind' } + key: value for key, value in vars(options).iteritems() if key.startswith('log')} runner = Mochitest(logger_options) options.runByDir = False if runner.getTestFlavor(options) == 'mochitest': options.runByDir = True if mozinfo.info['asan'] and options.e10s:
--- a/testing/mozbase/mozdebug/mozdebug/mozdebug.py +++ b/testing/mozbase/mozdebug/mozdebug/mozdebug.py @@ -6,18 +6,17 @@ import os import mozinfo from collections import namedtuple from distutils.spawn import find_executable __all__ = ['get_debugger_info', 'get_default_debugger_name', - 'DebuggerSearch', - 'get_default_valgrind_args'] + 'DebuggerSearch'] ''' Map of debugging programs to information about them, like default arguments and whether or not they are interactive. To add support for a new debugger, simply add the relative entry in _DEBUGGER_INFO and optionally update the _DEBUGGER_PRIORITIES. ''' @@ -45,16 +44,30 @@ To add support for a new debugger, simpl 'interactive': True, 'args': ['-debugexe'] }, # Visual C++ Express Debugger Support. 'wdexpress.exe': { 'interactive': True, 'args': ['-debugexe'] + }, + + # valgrind doesn't explain much about leaks unless you set the + # '--leak-check=full' flag. But there are a lot of objects that are + # semi-deliberately leaked, so we set '--show-possibly-lost=no' to avoid + # uninteresting output from those objects. We set '--smc-check==all-non-file' + # and '--vex-iropt-register-updates=allregs-at-mem-access' so that valgrind + # deals properly with JIT'd JavaScript code. + 'valgrind': { + 'interactive': False, + 'args': ['--leak-check=full', + '--show-possibly-lost=no', + '--smc-check=all-non-file', + '--vex-iropt-register-updates=allregs-at-mem-access'] } } # Maps each OS platform to the preferred debugger programs found in _DEBUGGER_INFO. _DEBUGGER_PRIORITIES = { 'win': ['devenv.exe', 'wdexpress.exe'], 'linux': ['gdb', 'cgdb', 'lldb'], 'mac': ['lldb', 'gdb'], @@ -148,72 +161,8 @@ def get_default_debugger_name(search=Deb for debuggerName in debuggerPriorities: debuggerPath = find_executable(debuggerName) if debuggerPath: return debuggerName elif not search == DebuggerSearch.KeepLooking: return None return None - -# Defines default values for Valgrind flags. -# -# --smc-check=all-non-file is required to deal with code generation and -# patching by the various JITS. Note that this is only necessary on -# x86 and x86_64, but not on ARM. This flag is only necessary for -# Valgrind versions prior to 3.11. -# -# --vex-iropt-register-updates=allregs-at-mem-access is required so that -# Valgrind generates correct register values whenever there is a -# segfault that is caught and handled. In particular OdinMonkey -# requires this. More recent Valgrinds (3.11 and later) provide -# --px-default=allregs-at-mem-access and -# --px-file-backed=unwindregs-at-mem-access -# which provide a significantly cheaper alternative, by restricting the -# precise exception behaviour to JIT generated code only. -# -# --trace-children=yes is required to get Valgrind to follow into -# content and other child processes. The resulting output can be -# difficult to make sense of, and --child-silent-after-fork=yes -# helps by causing Valgrind to be silent for the child in the period -# after fork() but before its subsequent exec(). -# -# --trace-children-skip lists processes that we are not interested -# in tracing into. -# -# --leak-check=full requests full stack traces for all leaked blocks -# detected at process exit. -# -# --show-possibly-lost=no requests blocks for which only an interior -# pointer was found to be considered not leaked. -# -# -# TODO: pass in the user supplied args for V (--valgrind-args=) and -# use this to detect if a different tool has been selected. If so -# adjust tool-specific args appropriately. -# -# TODO: pass in the path to the Valgrind to be used (--valgrind=), and -# check what flags it accepts. Possible args that might be beneficial: -# -# --num-transtab-sectors=24 [reduces re-jitting overheads in long runs] -# --px-default=allregs-at-mem-access -# --px-file-backed=unwindregs-at-mem-access -# [these reduce PX overheads as described above] -# -def get_default_valgrind_args(): - return (['--fair-sched=yes', - '--smc-check=all-non-file', - '--vex-iropt-register-updates=allregs-at-mem-access', - '--trace-children=yes', - '--child-silent-after-fork=yes', - '--leak-check=full', - '--show-possibly-lost=no', - ('--trace-children-skip=' - + '/usr/bin/hg,/bin/rm,*/bin/certutil,*/bin/pk12util,' - + '*/bin/ssltunnel,*/bin/uname,*/bin/which,*/bin/ps,' - + '*/bin/grep,*/bin/java'), - ] - + get_default_valgrind_tool_specific_args()) - -def get_default_valgrind_tool_specific_args(): - return [ - '--partial-loads-ok=yes' - ]
--- a/testing/mozbase/mozlog/mozlog/commandline.py +++ b/testing/mozbase/mozlog/mozlog/commandline.py @@ -34,19 +34,16 @@ def verbose_wrapper(formatter, verbose): def buffer_handler_wrapper(handler, buffer_limit): if buffer_limit == "UNLIMITED": buffer_limit = None else: buffer_limit = int(buffer_limit) return handlers.BufferHandler(handler, buffer_limit) -def valgrind_handler_wrapper(handler): - return handlers.ValgrindHandler(handler) - def default_formatter_options(log_type, overrides): formatter_option_defaults = { "raw": { "level": "debug" } } rv = {"verbose": False, "level": "info"} @@ -149,34 +146,27 @@ def setup_handlers(logger, formatters, f if unused_options: msg = ("Options specified for unused formatter(s) (%s) have no effect" % list(unused_options)) raise ValueError(msg) for fmt, streams in formatters.iteritems(): formatter_cls = log_formatters[fmt][0] formatter = formatter_cls() - handler_wrappers_and_options = [] - + handler_wrapper, handler_option = None, "" for option, value in formatter_options[fmt].iteritems(): - wrapper, wrapper_args = None, () - if option == "valgrind": - wrapper = valgrind_handler_wrapper - elif option == "buffer": - wrapper, wrapper_args = fmt_options[option][0], (value,) + if option == "buffer": + handler_wrapper, handler_option = fmt_options[option][0], value else: formatter = fmt_options[option][0](formatter, value) - if wrapper is not None: - handler_wrappers_and_options.append((wrapper, wrapper_args)) - for value in streams: handler = handlers.StreamHandler(stream=value, formatter=formatter) - for wrapper, wrapper_args in handler_wrappers_and_options: - handler = wrapper(handler, *wrapper_args) + if handler_wrapper: + handler = handler_wrapper(handler, handler_option) logger.add_handler(handler) def setup_logging(logger, args, defaults=None, formatter_defaults=None): """ Configure a structuredlogger based on command line arguments. The created structuredlogger will also be set as the default logger, and @@ -216,19 +206,17 @@ def setup_logging(logger, args, defaults defaults = {"mach": sys.stdout} else: defaults = {"raw": sys.stdout} for name, values in args.iteritems(): parts = name.split('_') if len(parts) > 3: continue - # Our args will be ['log', <formatter>] - # or ['log', <formatter>, <option>] - # or ['valgrind'] + # Our args will be ['log', <formatter>] or ['log', <formatter>, <option>]. if parts[0] == 'log' and values is not None: if len(parts) == 1 or parts[1] not in log_formatters: continue if len(parts) == 2: _, formatter = parts for value in values: found = True if isinstance(value, basestring): @@ -252,16 +240,12 @@ def setup_logging(logger, args, defaults for name, value in defaults.iteritems(): if value == sys.stdout: formatters[name].append(value) for name in formatters: if name not in formatter_options: formatter_options[name] = default_formatter_options(name, formatter_defaults) - # If the user specified --valgrind, add it as an option for all formatters - if args.get('valgrind', None) is not None: - for name in formatters: - formatter_options[name]['valgrind'] = True setup_handlers(logger, formatters, formatter_options) set_default_logger(logger) return logger
--- a/testing/mozbase/mozlog/mozlog/formatters/machformatter.py +++ b/testing/mozbase/mozlog/mozlog/formatters/machformatter.py @@ -227,23 +227,16 @@ class MachFormatter(base.BaseFormatter): for name, status, expected, message in unexpected: if name is None: name = "[Parent]" expected_str = "Expected %s, got %s" % (expected, status) rv += "%s\n" % ("\n".join([name, "-" * len(name), expected_str, message])) rv = rv[:-1] return rv - def valgrind_error(self, data): - rv = " " + data['primary'] + "\n" - for line in data['secondary']: - rv = rv + line + "\n" - - return rv - def test_status(self, data): self.summary_values["subtests"] += 1 test = self._get_test_id(data) if test not in self.status_buffer: self.status_buffer[test] = {"count": 0, "unexpected": [], "pass": 0} self.status_buffer[test]["count"] += 1
--- a/testing/mozbase/mozlog/mozlog/formatters/tbplformatter.py +++ b/testing/mozbase/mozlog/mozlog/formatters/tbplformatter.py @@ -144,15 +144,8 @@ class TbplFormatter(BaseFormatter): else: return tuple(test_id) def id_str(self, test_id): if isinstance(test_id, (str, unicode)): return test_id else: return " ".join(test_id) - - def valgrind_error(self, data): - rv = "TEST-VALGRIND-ERROR | " + data['primary'] + "\n" - for line in data['secondary']: - rv = rv + line + "\n" - - return rv
--- a/testing/mozbase/mozlog/mozlog/handlers/__init__.py +++ b/testing/mozbase/mozlog/mozlog/handlers/__init__.py @@ -1,8 +1,7 @@ # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. from .base import LogLevelFilter, StreamHandler, BaseHandler from .statushandler import StatusHandler from .bufferhandler import BufferHandler -from .valgrindhandler import ValgrindHandler
deleted file mode 100644 --- a/testing/mozbase/mozlog/mozlog/handlers/valgrindhandler.py +++ /dev/null @@ -1,137 +0,0 @@ -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -from .base import BaseHandler -import re - -class ValgrindHandler(BaseHandler): - - def __init__(self, inner): - BaseHandler.__init__(self, inner) - self.inner = inner - self.vFilter = ValgrindFilter() - - def __call__(self, data): - tmp = self.vFilter(data) - if tmp is not None: - self.inner(tmp) - -class ValgrindFilter(object): - ''' - A class for handling Valgrind output. - - Valgrind errors look like this: - - ==60741== 40 (24 direct, 16 indirect) bytes in 1 blocks are definitely lost in loss record 2,746 of 5,235 - ==60741== at 0x4C26B43: calloc (vg_replace_malloc.c:593) - ==60741== by 0x63AEF65: PR_Calloc (prmem.c:443) - ==60741== by 0x69F236E: PORT_ZAlloc_Util (secport.c:117) - ==60741== by 0x69F1336: SECITEM_AllocItem_Util (secitem.c:28) - ==60741== by 0xA04280B: ffi_call_unix64 (in /builds/slave/m-in-l64-valgrind-000000000000/objdir/toolkit/library/libxul.so) - ==60741== by 0xA042443: ffi_call (ffi64.c:485) - - For each such error, this class extracts most or all of the first (error - kind) line, plus the function name in each of the first few stack entries. - With this data it constructs and prints a TEST-UNEXPECTED-FAIL message that - TBPL will highlight. - - It buffers these lines from which text is extracted so that the - TEST-UNEXPECTED-FAIL message can be printed before the full error. - - Parsing the Valgrind output isn't ideal, and it may break in the future if - Valgrind changes the format of the messages, or introduces new error kinds. - To protect against this, we also count how many lines containing - "<insert_a_suppression_name_here>" are seen. Thanks to the use of - --gen-suppressions=yes, exactly one of these lines is present per error. If - the count of these lines doesn't match the error count found during - parsing, then the parsing has missed one or more errors and we can fail - appropriately. - ''' - - def __init__(self): - # The regexps in this list match all of Valgrind's errors. Note that - # Valgrind is English-only, so we don't have to worry about - # localization. - self.re_error = \ - re.compile( \ - r'==\d+== (' + \ - r'(Use of uninitialised value of size \d+)|' + \ - r'(Conditional jump or move depends on uninitialised value\(s\))|' + \ - r'(Syscall param .* contains uninitialised byte\(s\))|' + \ - r'(Syscall param .* points to (unaddressable|uninitialised) byte\(s\))|' + \ - r'((Unaddressable|Uninitialised) byte\(s\) found during client check request)|' + \ - r'(Invalid free\(\) / delete / delete\[\] / realloc\(\))|' + \ - r'(Mismatched free\(\) / delete / delete \[\])|' + \ - r'(Invalid (read|write) of size \d+)|' + \ - r'(Jump to the invalid address stated on the next line)|' + \ - r'(Source and destination overlap in .*)|' + \ - r'(.* bytes in .* blocks are .* lost)' + \ - r')' \ - ) - # Match identifer chars, plus ':' for namespaces, and '\?' in order to - # match "???" which Valgrind sometimes produces. - self.re_stack_entry = \ - re.compile(r'^==\d+==.*0x[A-Z0-9]+: ([A-Za-z0-9_:\?]+)') - self.re_suppression = \ - re.compile(r' *<insert_a_suppression_name_here>') - self.error_count = 0 - self.suppression_count = 0 - self.number_of_stack_entries_to_get = 0 - self.curr_failure_msg = "" - self.buffered_lines = [] - - # Takes a message and returns a message - def __call__(self, msg): - # Pass through everything that isn't plain text - if msg['action'] != 'log': - return msg - - line = msg['message'] - output_message = None - if self.number_of_stack_entries_to_get == 0: - # Look for the start of a Valgrind error. - m = re.search(self.re_error, line) - if m: - self.error_count += 1 - self.number_of_stack_entries_to_get = 4 - self.curr_failure_msg = m.group(1) + " at " - self.buffered_lines = [line] - else: - output_message = msg - - else: - # We've recently found a Valgrind error, and are now extracting - # details from the first few stack entries. - self.buffered_lines.append(line) - m = re.match(self.re_stack_entry, line) - if m: - self.curr_failure_msg += m.group(1) - else: - self.curr_failure_msg += '?!?' - - self.number_of_stack_entries_to_get -= 1 - if self.number_of_stack_entries_to_get != 0: - self.curr_failure_msg += ' / ' - else: - # We've finished getting the first few stack entries. Emit - # the failure action, comprising the primary message and the - # buffered lines, and then reset state. Copy the mandatory - # fields from the incoming message, since there's nowhere - # else to get them from. - output_message = { # Mandatory fields - u"action": "valgrind_error", - u"time": msg["time"], - u"thread": msg["thread"], - u"pid": msg["pid"], - u"source": msg["source"], - # valgrind_error specific fields - u"primary": self.curr_failure_msg, - u"secondary": self.buffered_lines } - self.curr_failure_msg = "" - self.buffered_lines = [] - - if re.match(self.re_suppression, line): - self.suppression_count += 1 - - return output_message
--- a/testing/mozbase/mozlog/mozlog/structuredlog.py +++ b/testing/mozbase/mozlog/mozlog/structuredlog.py @@ -357,21 +357,16 @@ class StructuredLogger(object): Unicode("stackwalk_stderr", default=None, optional=True), List("stackwalk_errors", Unicode, default=None)) def crash(self, data): if data["stackwalk_errors"] is None: data["stackwalk_errors"] = [] self._log_data("crash", data) - @log_action(Unicode("primary", default=None), - List("secondary", Unicode, default=None)) - def valgrind_error(self, data): - self._log_data("valgrind_error", data) - @log_action(Unicode("process"), Unicode("command", default=None, optional=True)) def process_start(self, data): """Log start event of a process. :param process: A unique identifier for the process producing the output (typically the pid) :param command: A string representing the full command line used to
--- a/testing/mozharness/mozharness/mozilla/structuredlog.py +++ b/testing/mozharness/mozharness/mozilla/structuredlog.py @@ -91,17 +91,16 @@ class StructuredOutputParser(OutputParse fail_pair = TBPL_WARNING, WARNING error_pair = TBPL_FAILURE, ERROR # These are warning/orange statuses. failure_conditions = [ sum(summary.unexpected_statuses.values()) > 0, summary.action_counts.get('crash', 0) > summary.expected_statuses.get('CRASH', 0), - summary.action_counts.get('valgrind_error', 0) > 0 ] for condition in failure_conditions: if condition: self.update_levels(*fail_pair) # These are error/red statuses. A message is output here every time something # wouldn't otherwise be highlighted in the UI. required_actions = {
--- a/testing/mozharness/mozharness/mozilla/testing/errors.py +++ b/testing/mozharness/mozharness/mozilla/testing/errors.py @@ -86,21 +86,16 @@ TinderBoxPrintRe = { }, "webapprt_summary": _mochitest_summary, "harness_error": { 'full_regex': re.compile(r"(?:TEST-UNEXPECTED-FAIL|PROCESS-CRASH) \| .* \| (application crashed|missing output line for total leaks!|negative leaks caught!|\d+ bytes leaked)"), 'minimum_regex': re.compile(r'''(TEST-UNEXPECTED|PROCESS-CRASH)'''), 'retry_regex': re.compile(r'''FAIL-SHOULD-RETRY''') }, - "valgrind_error": { - 'substr': 'TEST-VALGRIND-ERROR', - 'level': ERROR, - 'explanation': 'Valgrind detected memory errors during the run' - }, } TestPassed = [ {'regex': re.compile('''(TEST-INFO|TEST-KNOWN-FAIL|TEST-PASS|INFO \| )'''), 'level': INFO}, ] LogcatErrorList = [ {'substr': 'Fatal signal 11 (SIGSEGV)', 'level': ERROR, 'explanation': 'This usually indicates the B2G process has crashed'},