예제 #1
0
 def _monitor_tracing(self, trace_process, call_graph):
     calls = []
     last_line_was_empty = False  # call-stack ends when two empty lines follow eachother
     while self._thread_enabled:
         # If process died unexpectedly, report error
         if not trace_process.is_alive():
             self._thread_error = 'Tracing stopped unexpectedly'
             break
         output = trace_process.get_output()
         # call-stack ended
         if output == '\n' and last_line_was_empty:
             stack = parse_stack(calls)
             call_graph.load_edges(stack.edges)
             call_graph.load_nodes(stack.nodes)
             call_graph.init_colors()
             calls.clear()
         # new line after a regular output
         elif output == '\n':
             last_line_was_empty = True
         # regular output from bcc trace
         elif output:
             last_line_was_empty = False
             calls.append(output)
     # Terminate process when tracing is stopped by the user
     if trace_process.is_alive():
         trace_process.terminate()
         trace_process.join()
예제 #2
0
    def test_parse_stack_returns_empty_stack_for_header_only(self):
        stack = [
            "PID    TID    COMM         FUNC             ",
        ]

        result = parse_stack(stack)

        self.assertDictEqual(result.nodes, {})
        self.assertDictEqual(result.edges, {})
예제 #3
0
def load_trace_output_from_file_to_call_graph(file_path, call_graph):
    text = Path(file_path).read_text()
    call_graph.clear()
    stacks = [stack.split('\n') for stack in text.split('\n\n')]
    for stack in stacks:
        graph = parse_stack(stack)
        call_graph.load_edges(graph.edges)
        call_graph.load_nodes(graph.nodes)
    call_graph.init_colors()
예제 #4
0
    def test_parse_stack_returns_nodes_for_stack_with_one_call(self):
        stack = [
            "19059  19059  dummy_source1 func1",
            "-14",
            "b'func1+0x0 [dummy_source1]'"
        ]

        expected_nodes = [{'call_count': 1, 'name': 'func1', 'source': 'dummy_source1'}]
        result = parse_stack(stack)
        self.assertListEqual(list(result.nodes.values()), expected_nodes)
        self.assertListEqual(list(result.edges.values()), [])
예제 #5
0
    def test_parse_stack_returns_nodes_for_stack_with_params(self):
        stack = [
            "19059  19059  dummy_source1 func1        b'param1' b'param2'",
            "-14",
            "b'func1+0x0 [dummy_source1]'",
            "b'func2+0x26 [dummy_source1]'",
            "b'func3+0x17 [dummy_source2]'",
        ]

        result = parse_stack(stack)

        self.assertListEqual(
            sorted(list(result.nodes.values()), key = lambda i: i['name']),
            [
                {'call_count': 1, 'name': 'func1', 'source': 'dummy_source1'},
                {'call_count': 0, 'name': 'func2', 'source': 'dummy_source1'},
                {'call_count': 0, 'name': 'func3', 'source': 'dummy_source2'},
            ]
        )
        self.assertListEqual(
            sorted(list(result.edges.values()), key = lambda i: i['call_count']),
            [{'call_count': 0, 'param': []}, {'call_count': 1, 'param': ['param1', 'param2']}]
        )
예제 #6
0
    def test_parse_stack_returns_empty_graph_for_empty_stack(self):
        result = parse_stack([])

        self.assertDictEqual(result.nodes, {})
        self.assertDictEqual(result.edges, {})
예제 #7
0
    def test_parse_stack_returns_empty_graph_for_stack_with_no_calls_in_right_format(self):
        result = parse_stack(['no calls'])

        self.assertDictEqual(result.nodes, {})
        self.assertDictEqual(result.edges, {})