Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quellcode-Bibliothek tsan.py

  Sprache: Python
 

# 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/.

import re


class TSANErrorParser:
    """Parses ThreadSanitizer reports out of a process output stream and emits
    one ``tsan_error`` structured-log action per completed report.

    A TSan report spans many lines, opens with a
    ``WARNING|ERROR: ThreadSanitizer: <kind>`` line and closes with a
    ``SUMMARY: ThreadSanitizer: ...`` line. In between it carries one or more
    labeled sub-stacks (e.g. "Mutex M1 acquired here while holding mutex M0 in
    main thread:", "Write of size 8 ... by main thread:"). Each sub-stack is
    surfaced separately so a consumer can render it as its own profiler marker
    (a marker holds a single stack).

    Reports from different emitting processes can interleave in a merged output
    stream, so in-progress state is keyed by the emitting process id.
    """

    # Matches every report header, e.g.
    #   "WARNING: ThreadSanitizer: data race (pid=6257)"
    #   "==2708==ERROR: ThreadSanitizer: SEGV on unknown address 0x0 (pc ...)"
    # The pid is taken from "(pid=N)" when present, else from a leading "==N==".
    headerRegExp = re.compile(
        r"(?:==(?P<procpid>\d+)==)?(?:WARNING|ERROR): ThreadSanitizer: "
        r"(?P<kind>.+?)(?: \(pid=(?P<pid>\d+)\))?$"
    )
    # Trailing descriptive noise that follows the kind in signal reports
    # (SEGV/SIGBUS/...): "<kind> on unknown address 0x.. (pc 0x.. bp ..)".
    kindNoiseRegExp = re.compile(r" (?:on unknown address|\(pc 0x).*$")
    summaryRegExp = re.compile(r"SUMMARY: ThreadSanitizer: (?P<rest>.+)$")
    descriptionRegExp = re.compile(
        r"^  (?P<description>Cycle in lock order graph: .+)$"
    )
    labelRegExp = re.compile(r"^  (?P<label>\S.*):$")
    frameRegExp = re.compile(
        r"^\s*#(?P<n>\d+) (?P<body>.+) "
        r"\((?P<module>[^()\s]+)\+(?P<modoffset>0x[0-9a-fA-F]+)\)"
        r"(?: \(BuildId: [0-9a-fA-F]+\))?\s*$"
    )
    # A trailing token is a source location if it has a path separator or looks
    # like "name.ext", optionally followed by ":line" / ":line:col".
    fileLocRegExp = re.compile(r"(?:/|.+\.[A-Za-z0-9_]+(?::\d+){0,2}$)")
    fileLineColRegExp = re.compile(
        r"(?P<file>.+?)(?::(?P<line>\d+)(?::(?P<col>\d+))?)?$"
    )
    # Rust frames aren't demangled cleanly and carry a trailing ::h<hex> that
    # changes with compiler versions; see bug 1507350.
    rustRegExp = re.compile(r"::h[a-f0-9]{16}$")

    def __init__(self, logger, scope=None):
        self.logger = logger
        self.scope = scope
        # pid -> in-progress report dict
        self._reports = {}

    def log(self, line, pid=None, scope=None):
        line = line.rstrip("\r\n")

        header = self.headerRegExp.search(line)
        if header:
            # A new report ends any report still open on this stream.
            self._finish(pid)
            report_pid = header.group("pid"or header.group("procpid")
            self._reports[pid] = {
                "kind": self.kindNoiseRegExp.sub("", header.group("kind")),
                "pid": int(report_pid) if report_pid else None,
                "description"None,
                "scope": scope if scope is not None else self.scope,
                "stacks": [],
                "current"None,
            }
            return

        report = self._reports.get(pid)
        if report is None:
            return

        summary = self.summaryRegExp.search(line)
        if summary:
            report["signature"] = self._signature(report["kind"], summary.group("rest"))
            self._finish(pid)
            return

        description = self.descriptionRegExp.match(line)
        if description:
            report["description"] = description.group("description")
            return

        frame = self.frameRegExp.match(line)
        if frame:
            # Some reports (e.g. SEGV) list frames with no preceding label
            # line; collect them under an implicit, unlabeled stack.
            if report["current"is None:
                report["current"] = {"label""""stack": []}
                report["stacks"].append(report["current"])
            report["current"]["stack"].append(self._frame(frame))
            return

        label = self.labelRegExp.match(line)
        if label:
            report["current"] = {"label": label.group("label"), "stack": []}
            report["stacks"].append(report["current"])

    def flush(self):
        """Emit any reports left open by truncated output."""
        for pid in list(self._reports):
            self._finish(pid)

    def _finish(self, pid):
        report = self._reports.pop(pid, None)
        if report is None:
            return
        self.logger.tsan_error(
            kind=report["kind"],
            signature=report.get("signature", report["kind"]),
            pid=report["pid"],
            description=report["description"],
            stacks=[
                {"label": s["label"], "stack": s["stack"]} for s in report["stacks"]
            ],
            scope=report["scope"],
        )

    def _frame(self, match):
        body = match.group("body")
        func, fileloc = self._split_body(body)
        structured = {
            "function": self.rustRegExp.sub("", func),
            "module": match.group("module"),
            "module_offset": match.group("modoffset"),
        }
        if fileloc:
            fm = self.fileLineColRegExp.match(fileloc)
            structured["file"] = fm.group("file")
            if fm.group("line"):
                structured["line"] = int(fm.group("line"))
            if fm.group("col"):
                structured["column"] = int(fm.group("col"))
        return structured

    def _split_body(self, body):
        match = re.match(r"(?P<func>.*) (?P<fileloc>\S+)$", body)
        if match and self.fileLocRegExp.match(match.group("fileloc")):
            return match.group("func"), match.group("fileloc")
        return body, None

    def _signature(self, kind, rest):
        if kind and rest.startswith(kind):
            rest = rest[len(kind) :].strip()
        # Reduce a leading absolute path to its basename for readability,
        # keeping any ":line:col" and trailing " in <function>".
        match = re.match(r"/\S+/(?P<tail>[^/\s].*)$", rest)
        if match:
            return match.group("tail")
        return rest

Messung V0.5 in Prozent
C=87 H=100 G=93

¤ Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.0.4Bemerkung:  ¤

*Bot Zugriff






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=277311
#Domains=752002