Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(292)

Side by Side Diff: tools/findit/stacktrace.py

Issue 430943003: [Findit] Plain objects to represent and parse stack trace. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 # Copyright (c) 2014 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4 import os
5 import re
6 import findit_for_crash_utils as findit_utils
stgao 2014/07/31 01:52:24 How about adding a file crash_utils.py? And includ
jeun 2014/07/31 18:41:15 Done.
7
8
9 class Stacktrace(object):
stgao 2014/07/31 01:52:24 Rename to |StacktraceInfo|? Because it contains mu
jeun 2014/07/31 18:41:14 I named it stacktrace because this object exists o
stgao 2014/07/31 19:48:58 Sound good. In that case, the comment "Contains re
10 """Represents Stacktrace object.
11
12 Contains release build stacktrace and debug build stacktrace.
13 """
14
15 def __init__(self, stacktrace, chrome_build):
16 self.stack_list = []
17 self.ParseStacktrace(stacktrace, chrome_build)
18
19 def ParseStacktrace(self, stacktrace, chrome_build):
20 """Parses stacktrace and returns normalized stacktrace.
stgao 2014/07/31 01:52:24 We do not return anything within this function act
jeun 2014/07/31 18:41:15 Done.
21
22 If there are multiple stack frames within the stacktrace,
stgao 2014/07/31 01:52:24 What's the 'stack frame' here? Does it refer to a
jeun 2014/07/31 18:41:15 changed the description
23 it will parse each frame separately.
24
25 Args:
26 stacktrace: a string containing stacktrace
27 chrome_build: a string containing the job type of the crash
28
29 Returns:
30 A stack dictionary, where key 'release' containing the result of parsing
31 release build stacktrace and 'debug' containing the result from debug
32 build stacktrace. Parsed result from each stacktrace contains a list
33 of parsed result for each stack within the stacktrace, where a
34 parsed result is a list of stacktraceline objects.
35 """
36 # If the passed in string is empty, the object does not represent anything
37 if not stacktrace:
38 self.stack_list = None
39 return
40
41 stack_frame_index_pattern = re.compile(r'#\d+')
42
43 # Reset the stack list, and assume we start from main thread
stgao 2014/07/31 01:52:24 # Comments end with a period like this. Please al
jeun 2014/07/31 18:41:15 Done.
44 self.stack_list = []
45 stack_priority = 0
46 seen_zero = False
47 current_stack = CallStack(stack_priority)
48
49 for line in stacktrace:
50
51 # If this line does not represent the crashing information, continue
52 if not stack_frame_index_pattern.match(line):
53 continue
54
55 # Get the frame index from the line
56 parts = line.split()
57 stack_frame_index = int(parts[0][1:])
stgao 2014/07/31 01:52:25 Use regex to get the stack_frame_index instead of
jeun 2014/07/31 18:41:15 Done.
58
59 # If it is 0, we need to check if this is from freed or prev-alloc, or
60 # is from main thead
61 if stack_frame_index == 0:
62
63 # If this frame is from main thread
stgao 2014/07/31 01:52:24 frame?
jeun 2014/07/31 18:41:15 Done.
64 if not seen_zero:
stgao 2014/07/31 01:52:24 Could |seen_zero| be renamed to |seen_main_thread|
jeun 2014/07/31 18:41:15 Done.
65 seen_zero = True
66
67 # If this is from freed or prev-alloc, add the callstack we have
68 # to the list of callstacks, and increment the stack priority
69 else:
70 self.stack_list.append(current_stack)
71 stack_priority += 1
72 current_stack = CallStack(stack_priority)
73
74 # Parse function name, file path and line number from the line
75 parsed_stack_frame_line = self.ExtractFromStacktraceLine(
76 parts, chrome_build)
77
78 # If the line is malformed, ignore this line. Else, get the info
79 if not parsed_stack_frame_line:
80 continue
81 (function, file_path, crashed_line) = parsed_stack_frame_line
82
83 # Normalize the file path so that it can be compared to repository path
84 file_name = os.path.basename(file_path)
85 (component, file_path) = findit_utils.NormalizePathLinux(file_path)
86
87 # Currently supports only blink and chromium
88 if component == 'blink' or component == 'chromium':
89 current_stack.Add(
90 StacktraceLine(stack_frame_index, component, file_name,
91 function, file_path, crashed_line))
92
93 self.stack_list.append(current_stack)
stgao 2014/07/31 01:52:24 I think different builds (asan, lsan, tsan, msan)
jeun 2014/07/31 18:41:14 I agree that something needs to be done about this
94
95 def ExtractFromStacktraceLine(self, parts, chrome_build):
96 """Extracts information from stacktrace.
stgao 2014/07/31 01:52:25 stacktrace seems misused here. Should be stack fra
jeun 2014/07/31 18:41:15 Done.
97
98 Args:
99 parts: a list, stacktrace.split()
100 chrome_build: a string containing the job type
101 of this crash (e.g. linux_asan_chrome_mp)
102
103 Returns:
104 A triple containing the name of the function, the path of the file and
105 the line of crash
106 """
107 try:
108 # tsan has different stack frame style from other builds
109 if chrome_build.startswith('linux_tsan'):
110 crash_component = parts[-2]
stgao 2014/07/31 01:52:24 The way we guess |crash_component| here is hacky.
jeun 2014/07/31 18:41:15 This is just a totally mis named variable. changed
111 function = ' '.join(parts[1:-2])
112
113 else:
114 crash_component = parts[-1]
115 function = ' '.join(parts[3:-1])
116
117 # Get file path and line info from the line
118 file_and_line = crash_component.split(':')
119 file_path = file_and_line[0]
120 crashed_line = int(file_and_line[1])
121 return (function, file_path, crashed_line)
122
123 # Return None if the line is malformed
124 except IndexError:
125 return None
126 except ValueError:
127 return None
128
129 def __getitem__(self, index):
130 return self.stack_list[index]
131
132 def GetStackFromMainThread(self):
133 return self.stack_list[0]
134
135
136 class CallStack(object):
137 """Represents a call stack within a stacktrace.
138
139 It is a list of stacktraceline object, and the stack represented by
140 this object is from main thread, freed thread or previously-allocated thread.
141 """
142
143 def __init__(self, stack_priority):
144 self.line_list = []
stgao 2014/07/31 01:52:25 |line_list| -> |frames| or |frame_list|?
jeun 2014/07/31 18:41:15 Done.
145 self.priority = stack_priority
146
147 def Add(self, stacktrace_line):
148 self.line_list.append(stacktrace_line)
149
150 def GetFirstN(self, n):
stgao 2014/07/31 01:52:24 check out of boundary?
jeun 2014/07/31 18:41:15 Python automatically checks for boundary when usin
151 return self.line_list[:n]
152
153
154 class StacktraceLine(object):
155 """Represents a line in stacktrace.
stgao 2014/07/31 01:52:25 We refer this as stack frames. Maybe renaming it t
jeun 2014/07/31 18:41:15 Done.
156
157 Attributes:
158 stack_frame_index: index in the stacktrace
159 component: a component this line represents, such as blink, chrome, etc.
160 file_name: name of the file that crashed
stgao 2014/07/31 01:52:24 |file_name| could be derived from |file_path|. Cou
jeun 2014/07/31 18:41:15 Same as the comment in component_dictionary file.
161 function: function that caused the crash
162 file_path: path of the crashed file
163 crashed_line: line of the file that caused the crash
stgao 2014/07/31 01:52:25 Will |line_number| be more clear?
jeun 2014/07/31 18:41:15 changed to crashed_line_number
164 """
165
166 def __init__(self, stack_frame_index, component, file_name,
167 function, file_path, crashed_line):
168 self.stack_frame_index = stack_frame_index
169 self.component = component
170 self.file_name = file_name
171 self.function = function
172 self.file_path = file_path
173 self.crashed_line = crashed_line
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698