OLD | NEW |
---|---|
1 | 1 |
2 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 2 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
3 // Use of this source code is governed by a BSD-style license that can be | 3 // Use of this source code is governed by a BSD-style license that can be |
4 // found in the LICENSE file. | 4 // found in the LICENSE file. |
5 | 5 |
6 // crash_report.cc : Implementation crash reporting. | 6 // crash_report.cc : Implementation crash reporting. |
7 #include "chrome_frame/crash_reporting/crash_report.h" | 7 #include "chrome_frame/crash_reporting/crash_report.h" |
8 | 8 |
9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
10 #include "base/lock.h" | |
10 #include "breakpad/src/client/windows/handler/exception_handler.h" | 11 #include "breakpad/src/client/windows/handler/exception_handler.h" |
11 | 12 |
12 // TODO(joshia): factor out common code with chrome used for crash reporting | 13 // TODO(joshia): factor out common code with chrome used for crash reporting |
13 const wchar_t kGoogleUpdatePipeName[] = L"\\\\.\\pipe\\GoogleCrashServices\\"; | 14 const wchar_t kGoogleUpdatePipeName[] = L"\\\\.\\pipe\\GoogleCrashServices\\"; |
14 static google_breakpad::ExceptionHandler * g_breakpad = NULL; | 15 static google_breakpad::ExceptionHandler * g_breakpad = NULL; |
16 static Lock g_breakpad_lock; | |
Sigurður Ásgeirsson
2010/04/28 01:54:10
comment on what this lock protects, please. I'm no
robertshield
2010/04/28 10:45:57
Will add a comment in another patch. Generally: th
| |
15 | 17 |
16 // These minidump flag combinations have been tested safe agains the | 18 // These minidump flag combinations have been tested safe agains the |
17 // DbgHelp.dll version that ships with Windows XP SP2. | 19 // DbgHelp.dll version that ships with Windows XP SP2. |
18 const MINIDUMP_TYPE kSmallDumpType = static_cast<MINIDUMP_TYPE>( | 20 const MINIDUMP_TYPE kSmallDumpType = static_cast<MINIDUMP_TYPE>( |
19 MiniDumpWithProcessThreadData | // Get PEB and TEB. | 21 MiniDumpWithProcessThreadData | // Get PEB and TEB. |
20 MiniDumpWithUnloadedModules); // Get unloaded modules when available. | 22 MiniDumpWithUnloadedModules); // Get unloaded modules when available. |
21 | 23 |
22 const MINIDUMP_TYPE kLargerDumpType = static_cast<MINIDUMP_TYPE>( | 24 const MINIDUMP_TYPE kLargerDumpType = static_cast<MINIDUMP_TYPE>( |
23 MiniDumpWithProcessThreadData | // Get PEB and TEB. | 25 MiniDumpWithProcessThreadData | // Get PEB and TEB. |
24 MiniDumpWithUnloadedModules | // Get unloaded modules when available. | 26 MiniDumpWithUnloadedModules | // Get unloaded modules when available. |
(...skipping 15 matching lines...) Expand all Loading... | |
40 #pragma code_seg(pop) | 42 #pragma code_seg(pop) |
41 | 43 |
42 // Place code in .text$veh_m. | 44 // Place code in .text$veh_m. |
43 #pragma code_seg(push, ".text$vm") | 45 #pragma code_seg(push, ".text$vm") |
44 #include "chrome_frame/crash_reporting/vectored_handler-impl.h" | 46 #include "chrome_frame/crash_reporting/vectored_handler-impl.h" |
45 | 47 |
46 // Use Win32 API; use breakpad for dumps; checks for single (current) module. | 48 // Use Win32 API; use breakpad for dumps; checks for single (current) module. |
47 class CrashHandlerTraits : public Win32VEHTraits, | 49 class CrashHandlerTraits : public Win32VEHTraits, |
48 public ModuleOfInterestWithExcludedRegion { | 50 public ModuleOfInterestWithExcludedRegion { |
49 public: | 51 public: |
50 CrashHandlerTraits() : breakpad_(NULL) {} | 52 CrashHandlerTraits() {} |
51 void Init(google_breakpad::ExceptionHandler* breakpad) { | 53 |
52 breakpad_ = breakpad; | 54 // Note that breakpad_lock must be held when this is called. |
55 void Init(google_breakpad::ExceptionHandler* breakpad, Lock* breakpad_lock) { | |
56 DCHECK(breakpad); | |
57 DCHECK(breakpad_lock); | |
58 breakpad_lock->AssertAcquired(); | |
59 | |
53 Win32VEHTraits::InitializeIgnoredBlocks(); | 60 Win32VEHTraits::InitializeIgnoredBlocks(); |
54 ModuleOfInterestWithExcludedRegion::SetCurrentModule(); | 61 ModuleOfInterestWithExcludedRegion::SetCurrentModule(); |
55 // Pointers to static (non-extern) functions take the address of the | 62 // Pointers to static (non-extern) functions take the address of the |
56 // function's first byte, as opposed to an entry in the compiler generated | 63 // function's first byte, as opposed to an entry in the compiler generated |
57 // JMP table. In release builds /OPT:REF wipes away the JMP table, but debug | 64 // JMP table. In release builds /OPT:REF wipes away the JMP table, but debug |
58 // builds are not so lucky. | 65 // builds are not so lucky. |
59 ModuleOfInterestWithExcludedRegion::SetExcludedRegion(&veh_segment_start, | 66 ModuleOfInterestWithExcludedRegion::SetExcludedRegion(&veh_segment_start, |
60 &veh_segment_end); | 67 &veh_segment_end); |
61 } | 68 } |
62 | 69 |
63 void Shutdown() { | 70 void Shutdown() { |
64 breakpad_ = 0; | |
65 } | 71 } |
66 | 72 |
67 inline bool WriteDump(EXCEPTION_POINTERS* p) { | 73 inline bool WriteDump(EXCEPTION_POINTERS* p) { |
68 return breakpad_->WriteMinidumpForException(p); | 74 return WriteMinidumpForException(p); |
69 } | 75 } |
70 | |
71 private: | |
72 google_breakpad::ExceptionHandler* breakpad_; | |
73 }; | 76 }; |
74 | 77 |
75 class CrashHandler { | 78 class CrashHandler { |
76 public: | 79 public: |
77 CrashHandler() : veh_id_(NULL), handler_(&crash_api_) {} | 80 CrashHandler() : veh_id_(NULL), handler_(&crash_api_) {} |
78 bool Init(google_breakpad::ExceptionHandler* breakpad); | 81 |
82 // Note that breakpad_lock is used to protect accesses to breakpad and must | |
83 // be held when Init() is called. | |
84 bool Init(google_breakpad::ExceptionHandler* breakpad, Lock* breakpad_lock); | |
85 | |
79 void Shutdown(); | 86 void Shutdown(); |
80 private: | 87 private: |
81 VectoredHandlerT<CrashHandlerTraits> handler_; | 88 VectoredHandlerT<CrashHandlerTraits> handler_; |
82 CrashHandlerTraits crash_api_; | 89 CrashHandlerTraits crash_api_; |
83 void* veh_id_; | 90 void* veh_id_; |
84 | 91 |
85 static LONG WINAPI VectoredHandlerEntryPoint(EXCEPTION_POINTERS* exptrs); | 92 static LONG WINAPI VectoredHandlerEntryPoint(EXCEPTION_POINTERS* exptrs); |
86 }; | 93 }; |
87 | 94 |
88 static CrashHandler g_crash_handler; | 95 static CrashHandler g_crash_handler; |
89 | 96 |
90 // Turn off FPO optimization, so ::RtlCaptureStackBackTrace returns sane result. | 97 // Turn off FPO optimization, so ::RtlCaptureStackBackTrace returns sane result. |
91 #pragma optimize("y", off) | 98 #pragma optimize("y", off) |
92 LONG WINAPI CrashHandler::VectoredHandlerEntryPoint( | 99 LONG WINAPI CrashHandler::VectoredHandlerEntryPoint( |
93 EXCEPTION_POINTERS* exptrs) { | 100 EXCEPTION_POINTERS* exptrs) { |
94 return g_crash_handler.handler_.Handler(exptrs); | 101 return g_crash_handler.handler_.Handler(exptrs); |
95 } | 102 } |
96 #pragma optimize("y", on) | 103 #pragma optimize("y", on) |
97 | 104 |
98 #pragma code_seg(pop) | 105 #pragma code_seg(pop) |
99 | 106 |
100 bool CrashHandler::Init(google_breakpad::ExceptionHandler* breakpad) { | 107 bool CrashHandler::Init(google_breakpad::ExceptionHandler* breakpad, |
108 Lock* breakpad_lock) { | |
109 DCHECK(breakpad); | |
110 DCHECK(breakpad_lock); | |
111 breakpad_lock->AssertAcquired(); | |
112 | |
101 if (veh_id_) | 113 if (veh_id_) |
102 return true; | 114 return true; |
103 | 115 |
104 void* id = ::AddVectoredExceptionHandler(FALSE, &VectoredHandlerEntryPoint); | 116 void* id = ::AddVectoredExceptionHandler(FALSE, &VectoredHandlerEntryPoint); |
105 if (id != NULL) { | 117 if (id != NULL) { |
106 veh_id_ = id; | 118 veh_id_ = id; |
107 crash_api_.Init(breakpad); | 119 crash_api_.Init(breakpad, breakpad_lock); |
108 return true; | 120 return true; |
109 } | 121 } |
110 | 122 |
111 return false; | 123 return false; |
112 } | 124 } |
113 | 125 |
114 void CrashHandler::Shutdown() { | 126 void CrashHandler::Shutdown() { |
115 if (veh_id_) { | 127 if (veh_id_) { |
116 ::RemoveVectoredExceptionHandler(veh_id_); | 128 ::RemoveVectoredExceptionHandler(veh_id_); |
117 veh_id_ = NULL; | 129 veh_id_ = NULL; |
118 } | 130 } |
119 | 131 |
120 crash_api_.Shutdown(); | 132 crash_api_.Shutdown(); |
121 } | 133 } |
122 | 134 |
123 std::wstring GetCrashServerPipeName(const std::wstring& user_sid) { | 135 std::wstring GetCrashServerPipeName(const std::wstring& user_sid) { |
124 std::wstring pipe_name = kGoogleUpdatePipeName; | 136 std::wstring pipe_name = kGoogleUpdatePipeName; |
125 pipe_name += user_sid; | 137 pipe_name += user_sid; |
126 return pipe_name; | 138 return pipe_name; |
127 } | 139 } |
128 | 140 |
129 bool InitializeVectoredCrashReportingWithPipeName( | 141 bool InitializeVectoredCrashReportingWithPipeName( |
130 bool full_dump, | 142 bool full_dump, |
131 const wchar_t* pipe_name, | 143 const wchar_t* pipe_name, |
132 const std::wstring& dump_path, | 144 const std::wstring& dump_path, |
133 google_breakpad::CustomClientInfo* client_info) { | 145 google_breakpad::CustomClientInfo* client_info) { |
146 AutoLock lock(g_breakpad_lock); | |
134 if (g_breakpad) | 147 if (g_breakpad) |
135 return true; | 148 return true; |
136 | 149 |
137 if (dump_path.empty()) { | 150 if (dump_path.empty()) { |
138 return false; | 151 return false; |
139 } | 152 } |
140 | 153 |
141 // TODO(siggi): Consider switching to kSmallerDumpType post-beta. | 154 // TODO(siggi): Consider switching to kSmallerDumpType post-beta. |
142 MINIDUMP_TYPE dump_type = full_dump ? kFullDumpType : kLargerDumpType; | 155 MINIDUMP_TYPE dump_type = full_dump ? kFullDumpType : kLargerDumpType; |
143 g_breakpad = new google_breakpad::ExceptionHandler( | 156 g_breakpad = new google_breakpad::ExceptionHandler( |
144 dump_path, NULL, NULL, NULL, | 157 dump_path, NULL, NULL, NULL, |
145 google_breakpad::ExceptionHandler::HANDLER_INVALID_PARAMETER | | 158 google_breakpad::ExceptionHandler::HANDLER_INVALID_PARAMETER | |
146 google_breakpad::ExceptionHandler::HANDLER_PURECALL, dump_type, | 159 google_breakpad::ExceptionHandler::HANDLER_PURECALL, dump_type, |
147 pipe_name, client_info); | 160 pipe_name, client_info); |
148 | 161 |
149 if (!g_breakpad) | 162 if (!g_breakpad) |
150 return false; | 163 return false; |
151 | 164 |
152 if (!g_crash_handler.Init(g_breakpad)) { | 165 if (!g_crash_handler.Init(g_breakpad, &g_breakpad_lock)) { |
153 delete g_breakpad; | 166 delete g_breakpad; |
154 g_breakpad = NULL; | 167 g_breakpad = NULL; |
155 return false; | 168 return false; |
156 } | 169 } |
157 | 170 |
158 return true; | 171 return true; |
159 } | 172 } |
160 | 173 |
161 bool InitializeVectoredCrashReporting( | 174 bool InitializeVectoredCrashReporting( |
162 bool full_dump, | 175 bool full_dump, |
163 const wchar_t* user_sid, | 176 const wchar_t* user_sid, |
164 const std::wstring& dump_path, | 177 const std::wstring& dump_path, |
165 google_breakpad::CustomClientInfo* client_info) { | 178 google_breakpad::CustomClientInfo* client_info) { |
166 DCHECK(user_sid); | 179 DCHECK(user_sid); |
167 DCHECK(client_info); | 180 DCHECK(client_info); |
168 | 181 |
169 std::wstring pipe_name = GetCrashServerPipeName(user_sid); | 182 std::wstring pipe_name = GetCrashServerPipeName(user_sid); |
170 | 183 |
171 return InitializeVectoredCrashReportingWithPipeName(full_dump, | 184 return InitializeVectoredCrashReportingWithPipeName(full_dump, |
172 pipe_name.c_str(), | 185 pipe_name.c_str(), |
173 dump_path, | 186 dump_path, |
174 client_info); | 187 client_info); |
175 } | 188 } |
176 | 189 |
177 bool ShutdownVectoredCrashReporting() { | 190 bool ShutdownVectoredCrashReporting() { |
178 g_crash_handler.Shutdown(); | 191 g_crash_handler.Shutdown(); |
192 AutoLock lock(g_breakpad_lock); | |
179 delete g_breakpad; | 193 delete g_breakpad; |
180 g_breakpad = NULL; | 194 g_breakpad = NULL; |
181 return true; | 195 return true; |
182 } | 196 } |
197 | |
198 bool WriteMinidumpForException(EXCEPTION_POINTERS* p) { | |
199 AutoLock lock(g_breakpad_lock); | |
200 bool success = false; | |
201 if (g_breakpad) { | |
202 success = g_breakpad->WriteMinidumpForException(p); | |
203 } | |
204 return success; | |
205 } | |
OLD | NEW |