Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(301)

Unified Diff: src/client/mac/handler/exception_handler.cc

Issue 172001: Allow writing on-request minidumps with an exception stream on OS X (Closed)
Patch Set: Created 14 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/client/mac/handler/exception_handler.cc
===================================================================
--- a/src/client/mac/handler/exception_handler.cc
+++ b/src/client/mac/handler/exception_handler.cc
@@ -48,18 +48,23 @@
extern ProtectedMemoryAllocator *gBreakpadAllocator;
#endif
namespace google_breakpad {
using std::map;
+// Message ID telling the handler thread to write a dump.
Mark Mentovai 2010/12/08 20:57:19 Why did you pick such a weird order to put these m
Ted Mielczarek 2010/12/08 21:01:27 I think in the previous patch it was an artifact o
+static const mach_msg_id_t kWriteDumpMessage = 0;
// Message ID telling the handler thread to quit.
static const mach_msg_id_t kQuitMessage = 1;
+// Message ID telling the handler thread to write a dump and include
+// an exception stream.
+static const mach_msg_id_t kWriteDumpWithExceptionMessage = 2;
// These structures and techniques are illustrated in
// Mac OS X Internals, Amit Singh, ch 9.7
struct ExceptionMessage {
mach_msg_header_t header;
mach_msg_body_t body;
mach_msg_port_descriptor_t thread;
mach_msg_port_descriptor_t task;
@@ -267,47 +272,50 @@ ExceptionHandler::ExceptionHandler(Direc
MinidumpGenerator::GatherSystemInformation();
Setup(install_handler);
}
ExceptionHandler::~ExceptionHandler() {
Teardown();
}
-bool ExceptionHandler::WriteMinidump() {
+bool ExceptionHandler::WriteMinidump(bool write_exception_stream) {
// If we're currently writing, just return
if (use_minidump_write_mutex_)
return false;
use_minidump_write_mutex_ = true;
last_minidump_write_result_ = false;
// Lock the mutex. Since we just created it, this will return immediately.
if (pthread_mutex_lock(&minidump_write_mutex_) == 0) {
// Send an empty message to the handle port so that a minidump will
// be written
- SendEmptyMachMessage(false);
+ SendMessageToHandlerThread(write_exception_stream ?
+ kWriteDumpWithExceptionMessage
Mark Mentovai 2010/12/08 20:57:19 Style nit: indent this line by 4 more spaces, put
+ : kWriteDumpMessage);
// Wait for the minidump writer to complete its writing. It will unlock
// the mutex when completed
pthread_mutex_lock(&minidump_write_mutex_);
}
use_minidump_write_mutex_ = false;
UpdateNextID();
return last_minidump_write_result_;
}
// static
bool ExceptionHandler::WriteMinidump(const string &dump_path,
+ bool write_exception_stream,
MinidumpCallback callback,
void *callback_context) {
ExceptionHandler handler(dump_path, NULL, callback, callback_context, false,
NULL);
- return handler.WriteMinidump();
+ return handler.WriteMinidump(write_exception_stream);
}
// static
bool ExceptionHandler::WriteMinidumpForChild(mach_port_t child,
mach_port_t child_blamed_thread,
const string &dump_path,
MinidumpCallback callback,
void *callback_context) {
@@ -334,26 +342,27 @@ bool ExceptionHandler::WriteMinidumpForC
callback_context, result);
}
return result;
}
bool ExceptionHandler::WriteMinidumpWithException(int exception_type,
int exception_code,
int exception_subcode,
- mach_port_t thread_name) {
+ mach_port_t thread_name,
+ bool exit_after_write) {
bool result = false;
if (directCallback_) {
if (directCallback_(callback_context_,
exception_type,
exception_code,
exception_subcode,
thread_name) ) {
- if (exception_type && exception_code)
+ if (exit_after_write)
_exit(exception_type);
}
} else if (IsOutOfProcess()) {
if (exception_type && exception_code) {
// If this is a real exception, give the filter (if any) a chance to
// decide if this should be sent.
if (filter_ && !filter_(callback_context_))
return false;
@@ -385,17 +394,17 @@ bool ExceptionHandler::WriteMinidumpWith
// Call user specified callback (if any)
if (callback_) {
// If the user callback returned true and we're handling an exception
// (rather than just writing out the file), then we should exit without
// forwarding the exception to the next handler.
if (callback_(dump_path_c_, next_minidump_id_c_, callback_context_,
result)) {
- if (exception_type && exception_code)
+ if (exit_after_write)
_exit(exception_type);
}
}
}
return result;
}
@@ -532,19 +541,36 @@ void *ExceptionHandler::WaitForMessage(v
self->SuspendThreads();
#if USE_PROTECTED_ALLOCATIONS
if(gBreakpadAllocator)
gBreakpadAllocator->Unprotect();
#endif
+ mach_port_t thread = MACH_PORT_NULL;
+ int exception_type = 0;
+ int exception_code = 0;
+ if (receive.header.msgh_id == kWriteDumpWithExceptionMessage) {
+ thread = receive.thread.name;
+ exception_type = EXC_BREAKPOINT;
+#if defined (__i386__) || defined(__x86_64__)
+ exception_code = EXC_I386_BPT;
+#elif defined (__ppc__) || defined (__ppc64__)
+ exception_code = EXC_PPC_BREAKPOINT;
+#else
+ #error architecture not supported
Mark Mentovai 2010/12/08 20:57:19 Don’t indent preprocessor things.
+#endif
+ }
+
// Write out the dump and save the result for later retrieval
self->last_minidump_write_result_ =
- self->WriteMinidumpWithException(0, 0, 0, 0);
+ self->WriteMinidumpWithException(exception_type, exception_code,
+ 0, thread,
+ exception_type != EXC_BREAKPOINT);
self->UninstallHandler(false);
#if USE_PROTECTED_ALLOCATIONS
if(gBreakpadAllocator)
gBreakpadAllocator->Protect();
#endif
@@ -570,17 +596,17 @@ void *ExceptionHandler::WaitForMessage(v
#endif
int subcode = 0;
if (receive.exception == EXC_BAD_ACCESS && receive.code_count > 1)
subcode = receive.code[1];
// Generate the minidump with the exception data.
self->WriteMinidumpWithException(receive.exception, receive.code[0],
- subcode, receive.thread.name);
+ subcode, receive.thread.name, true);
self->UninstallHandler(true);
#if USE_PROTECTED_ALLOCATIONS
if(gBreakpadAllocator)
gBreakpadAllocator->Protect();
#endif
}
@@ -705,44 +731,50 @@ bool ExceptionHandler::Setup(bool instal
bool ExceptionHandler::Teardown() {
kern_return_t result = KERN_SUCCESS;
is_in_teardown_ = true;
if (!UninstallHandler(false))
return false;
// Send an empty message so that the handler_thread exits
- if (SendEmptyMachMessage(true)) {
+ if (SendMessageToHandlerThread(kQuitMessage)) {
mach_port_t current_task = mach_task_self();
result = mach_port_deallocate(current_task, handler_port_);
if (result != KERN_SUCCESS)
return false;
} else {
return false;
}
handler_thread_ = NULL;
handler_port_ = NULL;
pthread_mutex_destroy(&minidump_write_mutex_);
return result == KERN_SUCCESS;
}
-bool ExceptionHandler::SendEmptyMachMessage(bool quit) {
- ExceptionMessage empty;
- memset(&empty, 0, sizeof(empty));
- if (quit)
- empty.header.msgh_id = kQuitMessage;
- empty.header.msgh_size = sizeof(empty) - sizeof(empty.padding);
- empty.header.msgh_remote_port = handler_port_;
- empty.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND,
+bool ExceptionHandler::SendMessageToHandlerThread(mach_msg_id_t message_id) {
+ ExceptionMessage msg;
+ memset(&msg, 0, sizeof(msg));
+ msg.header.msgh_id = message_id;
+ if (message_id == kWriteDumpMessage ||
+ message_id == kWriteDumpWithExceptionMessage) {
+ // Include this thread's port.
+ msg.thread.name = mach_thread_self();
+ msg.thread.disposition = MACH_MSG_TYPE_PORT_SEND;
+ msg.thread.type = MACH_MSG_PORT_DESCRIPTOR;
+ }
+ msg.header.msgh_size = sizeof(msg) - sizeof(msg.padding);
+ msg.header.msgh_remote_port = handler_port_;
+ msg.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND,
MACH_MSG_TYPE_MAKE_SEND_ONCE);
- kern_return_t result = mach_msg(&(empty.header),
+ kern_return_t result = mach_msg(&(msg.header),
MACH_SEND_MSG | MACH_SEND_TIMEOUT,
- empty.header.msgh_size, 0, 0,
+ msg.header.msgh_size, 0, 0,
MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
return result == KERN_SUCCESS;
}
void ExceptionHandler::UpdateNextID() {
next_minidump_path_ =
(MinidumpGenerator::UniqueNameInDirectory(dump_path_, &next_minidump_id_));
« no previous file with comments | « no previous file | src/client/mac/handler/exception_handler.h » ('j') | src/client/mac/handler/exception_handler.h » ('J')

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld 1004:630ec63f810e-tainted