Bug 1507550 - Scrub out junk from rust signatures when processing LSAN data, r=mccr8
authorJames Graham <james@hoppipolla.co.uk>
Mon, 19 Nov 2018 15:29:46 +0000
changeset 503699 6beca6ad237ecb0d709350380c9b83003f5f577c
parent 503698 7825009998ae5d5bebef3096a332918ed18defb6
child 503700 4700d8714486d2982443ff7d703b7b16402ec76a
push id10290
push userffxbld-merge
push dateMon, 03 Dec 2018 16:23:23 +0000
treeherdermozilla-beta@700bed2445e6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmccr8
bugs1507550
milestone65.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1507550 - Scrub out junk from rust signatures when processing LSAN data, r=mccr8 Rust signatures aren't properly demangled, and contain some trailing data that seems to depend on the compiler version. This defeats the attempt to allow LSAN errors when importing tests, and we end up adding multiple variants of the same symbol to the allow list. To avoid this, simply preprocess the symbols not to contain the trailing junk when reading LSAN output, whilst we await better demangling. Differential Revision: https://phabricator.services.mozilla.com/D12303
testing/mozbase/moz.build
testing/mozbase/mozleak/mozleak/lsan.py
testing/mozbase/mozleak/tests/manifest.ini
testing/mozbase/mozleak/tests/test_lsan.py
--- a/testing/mozbase/moz.build
+++ b/testing/mozbase/moz.build
@@ -8,16 +8,17 @@ PYTHON_UNITTEST_MANIFESTS += [
     'manifestparser/tests/manifest.ini',
     'mozcrash/tests/manifest.ini',
     'mozdebug/tests/manifest.ini',
     'mozdevice/tests/manifest.ini',
     'mozfile/tests/manifest.ini',
     'mozhttpd/tests/manifest.ini',
     'mozinfo/tests/manifest.ini',
     'mozinstall/tests/manifest.ini',
+    'mozleak/tests/manifest.ini',
     'mozlog/tests/manifest.ini',
     'moznetwork/tests/manifest.ini',
     'mozprocess/tests/manifest.ini',
     'mozprofile/tests/manifest.ini',
     'mozrunner/tests/manifest.ini',
     'moztest/tests/manifest.ini',
     'mozversion/tests/manifest.ini',
 ]
--- a/testing/mozbase/mozleak/mozleak/lsan.py
+++ b/testing/mozbase/mozleak/mozleak/lsan.py
@@ -45,16 +45,17 @@ class LSANLeaks(object):
             "==\d+==LeakSanitizer has encountered a fatal error.")
         self.symbolizerOomRegExp = re.compile(
             "LLVMSymbolizer: error reading file: Cannot allocate memory")
         self.stackFrameRegExp = re.compile("    #\d+ 0x[0-9a-f]+ in ([^(</]+)")
         self.sysLibStackFrameRegExp = re.compile(
             "    #\d+ 0x[0-9a-f]+ \(([^+]+)\+0x[0-9a-f]+\)")
         self.summaryRegexp = re.compile(
             "SUMMARY: AddressSanitizer: (\d+) byte\(s\) leaked in (\d+) allocation\(s\).")
+        self.rustRegexp = re.compile("::h[a-f0-9]{16}$")
         self.setAllowed(allowed)
 
     def setAllowed(self, allowedLines):
         if not allowedLines:
             self.allowedRegexp = None
         else:
             self.allowedRegexp = re.compile(
                 "^" + "|".join([re.escape(f) for f in allowedLines]))
@@ -161,12 +162,19 @@ class LSANLeaks(object):
             self.currStack = None
             self.allowedMatch = None
         self.recordMoreFrames = False
         self.numRecordedFrames = 0
 
     def _recordFrame(self, frame):
         if self.allowedMatch is None and self.allowedRegexp is not None:
             self.allowedMatch = frame if self.allowedRegexp.match(frame) else None
+        frame = self._cleanFrame(frame)
         self.currStack.append(frame)
         self.numRecordedFrames += 1
         if self.numRecordedFrames >= self.maxNumRecordedFrames:
             self.recordMoreFrames = False
+
+    def _cleanFrame(self, frame):
+        # Rust frames aren't properly demangled and in particular can contain
+        # some trailing junk of the form ::h[a-f0-9]{16} that changes with
+        # compiler versions; see bug 1507350.
+        return self.rustRegexp.sub("", frame)
new file mode 100644
--- /dev/null
+++ b/testing/mozbase/mozleak/tests/manifest.ini
@@ -0,0 +1,4 @@
+[DEFAULT]
+subsuite = mozbase, os == "linux"
+[test_lsan.py]
+skip-if = python == 3
new file mode 100644
--- /dev/null
+++ b/testing/mozbase/mozleak/tests/test_lsan.py
@@ -0,0 +1,24 @@
+from __future__ import absolute_import
+import pytest
+
+import mozunit
+from mozleak import lsan
+
+
+@pytest.mark.parametrize(("input_", "expected"),
+                         [("alloc_system::platform::_$LT$impl$u20$core..alloc.."
+                           "GlobalAlloc$u20$for$u20$alloc_system..System$GT$::"
+                           "alloc::h5a1f0db41e296502",
+                           "alloc_system::platform::_$LT$impl$u20$core..alloc.."
+                           "GlobalAlloc$u20$for$u20$alloc_system..System$GT$::alloc"),
+                          ("alloc_system::platform::_$LT$impl$u20$core..alloc.."
+                           "GlobalAlloc$u20$for$u20$alloc_system..System$GT$::alloc",
+                           "alloc_system::platform::_$LT$impl$u20$core..alloc.."
+                           "GlobalAlloc$u20$for$u20$alloc_system..System$GT$::alloc")])
+def test_clean(input_, expected):
+    leaks = lsan.LSANLeaks(None)
+    assert leaks._cleanFrame(input_) == expected
+
+
+if __name__ == '__main__':
+    mozunit.main()