Eliminate another source of UnspecifiedStackSignature crash dumps.

Manufacturing an exception record improves the crash reporting, since then
the crashes get bucketed by the call stack leading to the dump, instead of 
all falling into a misc bucket that nobody ever looks at.
Currently these are occuring through e.g. dumps from the base watchdog.

Link against RtlCaptureContext, as the function has been documented as
available
from Windows XP
[http://msdn.microsoft.com/en-us/library/windows/desktop/ms680591(v=vs.85).aspx].

Patch by Siggi Asgeirsson <siggi@chromium.org>


git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@897 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
mark@chromium.org 2011-12-21 22:09:56 +00:00
parent ae5193c24e
commit 5951dd28af

View file

@ -39,8 +39,6 @@
#include "client/windows/handler/exception_handler.h"
#include "common/windows/guid_string.h"
typedef VOID (WINAPI *RtlCaptureContextPtr) (PCONTEXT pContextRecord);
namespace google_breakpad {
static const int kWaitForHandlerThreadMs = 60000;
@ -498,27 +496,19 @@ void ExceptionHandler::HandleInvalidParameter(const wchar_t* expression,
CONTEXT exception_context = {};
EXCEPTION_POINTERS exception_ptrs = { &exception_record, &exception_context };
EXCEPTION_POINTERS* exinfo = NULL;
::RtlCaptureContext(&exception_context);
RtlCaptureContextPtr fnRtlCaptureContext = (RtlCaptureContextPtr)
GetProcAddress(GetModuleHandleW(L"kernel32"), "RtlCaptureContext");
if (fnRtlCaptureContext) {
fnRtlCaptureContext(&exception_context);
exception_record.ExceptionCode = STATUS_INVALID_PARAMETER;
exception_record.ExceptionCode = STATUS_NONCONTINUABLE_EXCEPTION;
// We store pointers to the the expression and function strings,
// and the line as exception parameters to make them easy to
// access by the developer on the far side.
exception_record.NumberParameters = 3;
exception_record.ExceptionInformation[0] =
reinterpret_cast<ULONG_PTR>(&assertion.expression);
exception_record.ExceptionInformation[1] =
reinterpret_cast<ULONG_PTR>(&assertion.file);
exception_record.ExceptionInformation[2] = assertion.line;
exinfo = &exception_ptrs;
}
// We store pointers to the the expression and function strings,
// and the line as exception parameters to make them easy to
// access by the developer on the far side.
exception_record.NumberParameters = 3;
exception_record.ExceptionInformation[0] =
reinterpret_cast<ULONG_PTR>(&assertion.expression);
exception_record.ExceptionInformation[1] =
reinterpret_cast<ULONG_PTR>(&assertion.file);
exception_record.ExceptionInformation[2] = assertion.line;
bool success = false;
// In case of out-of-process dump generation, directly call
@ -526,10 +516,10 @@ void ExceptionHandler::HandleInvalidParameter(const wchar_t* expression,
if (current_handler->IsOutOfProcess()) {
success = current_handler->WriteMinidumpWithException(
GetCurrentThreadId(),
exinfo,
&exception_ptrs,
&assertion);
} else {
success = current_handler->WriteMinidumpOnHandlerThread(exinfo,
success = current_handler->WriteMinidumpOnHandlerThread(&exception_ptrs,
&assertion);
}
@ -586,27 +576,19 @@ void ExceptionHandler::HandlePureVirtualCall() {
CONTEXT exception_context = {};
EXCEPTION_POINTERS exception_ptrs = { &exception_record, &exception_context };
EXCEPTION_POINTERS* exinfo = NULL;
::RtlCaptureContext(&exception_context);
RtlCaptureContextPtr fnRtlCaptureContext = (RtlCaptureContextPtr)
GetProcAddress(GetModuleHandleW(L"kernel32"), "RtlCaptureContext");
if (fnRtlCaptureContext) {
fnRtlCaptureContext(&exception_context);
exception_record.ExceptionCode = STATUS_NONCONTINUABLE_EXCEPTION;
exception_record.ExceptionCode = STATUS_NONCONTINUABLE_EXCEPTION;
// We store pointers to the the expression and function strings,
// and the line as exception parameters to make them easy to
// access by the developer on the far side.
exception_record.NumberParameters = 3;
exception_record.ExceptionInformation[0] =
reinterpret_cast<ULONG_PTR>(&assertion.expression);
exception_record.ExceptionInformation[1] =
reinterpret_cast<ULONG_PTR>(&assertion.file);
exception_record.ExceptionInformation[2] = assertion.line;
exinfo = &exception_ptrs;
}
// We store pointers to the the expression and function strings,
// and the line as exception parameters to make them easy to
// access by the developer on the far side.
exception_record.NumberParameters = 3;
exception_record.ExceptionInformation[0] =
reinterpret_cast<ULONG_PTR>(&assertion.expression);
exception_record.ExceptionInformation[1] =
reinterpret_cast<ULONG_PTR>(&assertion.file);
exception_record.ExceptionInformation[2] = assertion.line;
bool success = false;
// In case of out-of-process dump generation, directly call
@ -615,10 +597,10 @@ void ExceptionHandler::HandlePureVirtualCall() {
if (current_handler->IsOutOfProcess()) {
success = current_handler->WriteMinidumpWithException(
GetCurrentThreadId(),
exinfo,
&exception_ptrs,
&assertion);
} else {
success = current_handler->WriteMinidumpOnHandlerThread(exinfo,
success = current_handler->WriteMinidumpOnHandlerThread(&exception_ptrs,
&assertion);
}
@ -678,7 +660,18 @@ bool ExceptionHandler::WriteMinidumpOnHandlerThread(
}
bool ExceptionHandler::WriteMinidump() {
return WriteMinidumpForException(NULL);
// Make up an exception record for the current thread and CPU context
// to make it possible for the crash processor to classify these
// as do regular crashes, and to make it humane for developers to
// analyze them.
EXCEPTION_RECORD exception_record = {};
CONTEXT exception_context = {};
EXCEPTION_POINTERS exception_ptrs = { &exception_record, &exception_context };
::RtlCaptureContext(&exception_context);
exception_record.ExceptionCode = STATUS_NONCONTINUABLE_EXCEPTION;
return WriteMinidumpForException(&exception_ptrs);
}
bool ExceptionHandler::WriteMinidumpForException(EXCEPTION_POINTERS* exinfo) {