OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #import "chrome/app/breakpad_mac.h" | 5 #import "chrome/app/breakpad_mac.h" |
6 | 6 |
7 #include <CoreFoundation/CoreFoundation.h> | 7 #include <CoreFoundation/CoreFoundation.h> |
8 #import <Foundation/Foundation.h> | 8 #import <Foundation/Foundation.h> |
9 | 9 |
10 #include "base/auto_reset.h" | 10 #include "base/auto_reset.h" |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
131 DumpHelper() {} | 131 DumpHelper() {} |
132 | 132 |
133 virtual void ThreadMain() OVERRIDE { | 133 virtual void ThreadMain() OVERRIDE { |
134 base::PlatformThread::SetName("CrDumpHelper"); | 134 base::PlatformThread::SetName("CrDumpHelper"); |
135 BreakpadGenerateAndSendReport(gBreakpadRef); | 135 BreakpadGenerateAndSendReport(gBreakpadRef); |
136 } | 136 } |
137 | 137 |
138 DISALLOW_COPY_AND_ASSIGN(DumpHelper); | 138 DISALLOW_COPY_AND_ASSIGN(DumpHelper); |
139 }; | 139 }; |
140 | 140 |
141 void SIGABRTHandler(int signal) { | |
142 // The OSX abort() (link below) masks all signals for the process, | |
143 // and all except SIGABRT for the thread. SIGABRT will be masked | |
144 // when the SIGABRT is sent, which means at this point only SIGKILL | |
145 // and SIGSTOP can be delivered. Unmask others so that the code | |
146 // below crashes as desired. | |
147 // | |
148 // http://www.opensource.apple.com/source/Libc/Libc-825.26/stdlib/FreeBSD/abor t.c | |
149 sigset_t mask; | |
150 sigemptyset(&mask); | |
151 sigaddset(&mask, signal); | |
152 pthread_sigmask(SIG_SETMASK, &mask, NULL); | |
153 | |
154 // Most interesting operations are not safe in a signal handler, just crash. | |
155 char* volatile death_ptr = NULL; | |
156 *death_ptr = '!'; | |
157 } | |
158 | |
141 } // namespace | 159 } // namespace |
142 | 160 |
143 bool IsCrashReporterEnabled() { | 161 bool IsCrashReporterEnabled() { |
144 return gBreakpadRef != NULL; | 162 return gBreakpadRef != NULL; |
145 } | 163 } |
146 | 164 |
147 // Only called for a branded build of Chrome.app. | 165 // Only called for a branded build of Chrome.app. |
148 void InitCrashReporter() { | 166 void InitCrashReporter() { |
149 DCHECK(!gBreakpadRef); | 167 DCHECK(!gBreakpadRef); |
150 base::mac::ScopedNSAutoreleasePool autorelease_pool; | 168 base::mac::ScopedNSAutoreleasePool autorelease_pool; |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
267 | 285 |
268 if (!is_browser) { | 286 if (!is_browser) { |
269 // Get the guid from the command line switch. | 287 // Get the guid from the command line switch. |
270 std::string guid = | 288 std::string guid = |
271 command_line->GetSwitchValueASCII(switches::kEnableCrashReporter); | 289 command_line->GetSwitchValueASCII(switches::kEnableCrashReporter); |
272 child_process_logging::SetClientId(guid); | 290 child_process_logging::SetClientId(guid); |
273 } | 291 } |
274 | 292 |
275 logging::SetLogMessageHandler(&FatalMessageHandler); | 293 logging::SetLogMessageHandler(&FatalMessageHandler); |
276 logging::SetDumpWithoutCrashingFunction(&DumpHelper::DumpWithoutCrashing); | 294 logging::SetDumpWithoutCrashingFunction(&DumpHelper::DumpWithoutCrashing); |
295 | |
296 // abort() sends SIGABRT, which breakpad does not intercept. | |
297 // Register a signal handler to crash in a way breakpad will | |
298 // intercept. | |
Nico
2013/05/23 21:27:50
Why doesn't breakpad do that?
Scott Hess - ex-Googler
2013/05/23 21:32:59
One day on the bug, Mark said "Mac Breakpad doesn’
| |
299 struct sigaction sigact; | |
300 memset(&sigact, 0, sizeof(sigact)); | |
301 sigact.sa_handler = SIGABRTHandler; | |
302 CHECK(0 == sigaction(SIGABRT, &sigact, NULL)); | |
277 } | 303 } |
278 | 304 |
279 void InitCrashProcessInfo() { | 305 void InitCrashProcessInfo() { |
280 if (gBreakpadRef == NULL) { | 306 if (gBreakpadRef == NULL) { |
281 return; | 307 return; |
282 } | 308 } |
283 | 309 |
284 // Determine the process type. | 310 // Determine the process type. |
285 NSString* process_type = @"browser"; | 311 NSString* process_type = @"browser"; |
286 std::string process_type_switch = | 312 std::string process_type_switch = |
287 CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | 313 CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |
288 switches::kProcessType); | 314 switches::kProcessType); |
289 if (!process_type_switch.empty()) { | 315 if (!process_type_switch.empty()) { |
290 process_type = base::SysUTF8ToNSString(process_type_switch); | 316 process_type = base::SysUTF8ToNSString(process_type_switch); |
291 } | 317 } |
292 | 318 |
293 #if !defined(DISABLE_NACL) | 319 #if !defined(DISABLE_NACL) |
294 if (process_type_switch == switches::kNaClLoaderProcess) { | 320 if (process_type_switch == switches::kNaClLoaderProcess) { |
295 BreakpadSetFilterCallback(gBreakpadRef, NaClBreakpadCrashFilter, NULL); | 321 BreakpadSetFilterCallback(gBreakpadRef, NaClBreakpadCrashFilter, NULL); |
296 } | 322 } |
297 #endif | 323 #endif |
298 | 324 |
299 // Store process type in crash dump. | 325 // Store process type in crash dump. |
300 SetCrashKeyValue(@"ptype", process_type); | 326 SetCrashKeyValue(@"ptype", process_type); |
301 } | 327 } |
OLD | NEW |