Esempio n. 1
0
class TSanReportExtractor(ReportExtractor):
    """Extract ThreadSanitizer reports"""

    __category_names = ['data race', 'thread leak']

    __start_line_pattern = re.compile(
        '^warning: threadsanitizer: (?P<category>[a-z ]+) \(', re.IGNORECASE)
    __start_last_line_pattern = re.compile('^={18}$', re.MULTILINE)
    __end_line_pattern = __start_last_line_pattern

    def __init__(self, options):
        super(TSanReportExtractor,
              self).__init__(options, Sanitizer('ThreadSanitizer', 'tsan'))
        self.__printer = Printer(options)

    def collect(self):
        for category in self.__category_names:
            self._collect_reports(category)

    def extract(self, last_line, line):
        if self._extract_continue(line):
            if self.__end_line_pattern.search(line):
                self._extract_end()
        else:
            search = self.__start_line_pattern.search(line)
            if search and self.__start_last_line_pattern.search(last_line):
                category = search.group('category').lower()
                if not category in self.__category_names:
                    self.__printer.bailout('unkown category ' + repr(category))
                else:
                    self._extract_start(
                        self._make_and_add_report(True, category))
                    self._extract_continue(last_line + line)
Esempio n. 2
0
class TaskEliminateDuplicateReports(object):

    description = 'Eliminating duplicate reports ...'

    __tsan_data_race_max_stack_frames = 3

    def __init__(self, bank):
        self.__bank = bank

    def setup(self, options):
        self.__printer = Printer(options)
        self.__duplicate_reports = []
        self.__identifiers_funcs = {
            'tsan': {
                'data race': self.__tsan_data_race_identifiers,
                'thread leak': self.__tsan_thread_leak_identifiers
            }
        }
        # TODO: split into separate lists for sanitizers and categories for better performance
        self.__known_identifiers = []

    def process(self, report):
        if not self.__identifiers_funcs.get(report.sanitizer.name_short,
                                            {}).get(report.category_name):
            self.__printer.bailout('unable to analyse ' + str(report))
        identifiers = self.__identifiers_funcs[report.sanitizer.name_short][
            report.category_name](report)
        if not identifiers:
            self.__printer.bailout('unable to extract identifiers from ' +
                                   str(report))
        for identifier in identifiers:
            if identifier in self.__known_identifiers:
                self.__printer.task_info('removing ' + str(report))
                self.__duplicate_reports.append(report)
                return
        self.__known_identifiers.extend(identifiers)

    def teardown(self):
        for report in self.__duplicate_reports:
            self.__bank.remove_report(report)

    def __tsan_data_race_identifiers(self, report):
        fragments = []
        for stack in report.call_stacks:
            if 'tsan_data_race_type' in stack.special:
                fragment = [
                    stack.special.get('tsan_data_race_type'),
                    stack.special.get('tsan_data_race_bytes')
                ]
                for i in range(
                        min(len(stack.frames),
                            self.__tsan_data_race_max_stack_frames)):
                    fragment.extend([
                        stack.frames[i].src_file_rel_path,
                        stack.frames[i].func_name, stack.frames[i].line_num,
                        stack.frames[i].char_pos
                    ])
                fragments.append(':'.join(
                    ['?' if not f else str(f) for f in fragment]))
        if len(fragments) == 1:
            return fragments
        if len(fragments) == 2:
            # either way is fine!
            return [
                fragments[0] + ':' + fragments[1],
                fragments[1] + ':' + fragments[0]
            ]

    def __tsan_thread_leak_identifiers(self, report):
        for stack in report.call_stacks:
            if stack.special.get('tsan_thread_leak_thread_name'):
                return [stack.special['tsan_thread_leak_thread_name']]