diff options
author | Tad Marshall <tad@10gen.com> | 2012-12-07 08:03:45 -0500 |
---|---|---|
committer | Tad Marshall <tad@10gen.com> | 2012-12-07 11:21:01 -0500 |
commit | 90440532fca3ce59383ad7e36437191f4819b3fc (patch) | |
tree | 5373b1f780a019ac5856a5e35a8bd9a64e4888f7 /src/mongo/util/exception_filter_win32.cpp | |
parent | 9fe63411b92a2469d364f4678f04830fdc9e4a38 (diff) | |
download | mongo-90440532fca3ce59383ad7e36437191f4819b3fc.tar.gz |
SERVER-6716 Add Windows unhandled exception filter to mongos
Move code for displaying access violations and other unhandled exceptions
from mongo/db/db.cpp to a new mongo/util/exception_filter_win32.cpp file,
invoke it from mongod.exe and mongos.exe.
Diffstat (limited to 'src/mongo/util/exception_filter_win32.cpp')
-rw-r--r-- | src/mongo/util/exception_filter_win32.cpp | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/src/mongo/util/exception_filter_win32.cpp b/src/mongo/util/exception_filter_win32.cpp new file mode 100644 index 00000000000..252f59bde96 --- /dev/null +++ b/src/mongo/util/exception_filter_win32.cpp @@ -0,0 +1,130 @@ +/** +* Copyright (C) 2012 10gen Inc. +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU Affero General Public License, version 3, +* as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Affero General Public License for more details. +* +* You should have received a copy of the GNU Affero General Public License +* along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifdef _WIN32 + +#include <ostream> + +#include "mongo/platform/basic.h" +#include <DbgHelp.h> +#include "mongo/util/assert_util.h" +#include "mongo/util/exit_code.h" +#include "mongo/util/log.h" +#include "mongo/util/stacktrace.h" + +namespace mongo { + + /* create a process dump. + To use, load up windbg. Set your symbol and source path. + Open the crash dump file. To see the crashing context, use .ecxr + */ + void doMinidump(struct _EXCEPTION_POINTERS* exceptionInfo) { + LPCWSTR dumpFilename = L"mongo.dmp"; + HANDLE hFile = CreateFileW(dumpFilename, + GENERIC_WRITE, + 0, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + if ( INVALID_HANDLE_VALUE == hFile ) { + DWORD lasterr = GetLastError(); + log() << "failed to open minidump file " << toUtf8String(dumpFilename) << " : " + << errnoWithDescription( lasterr ) << std::endl; + return; + } + + MINIDUMP_EXCEPTION_INFORMATION aMiniDumpInfo; + aMiniDumpInfo.ThreadId = GetCurrentThreadId(); + aMiniDumpInfo.ExceptionPointers = exceptionInfo; + aMiniDumpInfo.ClientPointers = TRUE; + + log() << "writing minidump diagnostic file " << toUtf8String(dumpFilename) << std::endl; + BOOL bstatus = MiniDumpWriteDump(GetCurrentProcess(), + GetCurrentProcessId(), + hFile, + MiniDumpNormal, + &aMiniDumpInfo, + NULL, + NULL); + if ( FALSE == bstatus ) { + DWORD lasterr = GetLastError(); + log() << "failed to create minidump : " + << errnoWithDescription( lasterr ) << std::endl; + } + + CloseHandle(hFile); + } + + LONG WINAPI exceptionFilter( struct _EXCEPTION_POINTERS *excPointers ) { + char exceptionString[128]; + sprintf_s( exceptionString, sizeof( exceptionString ), + ( excPointers->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION ) ? + "(access violation)" : "0x%08X", excPointers->ExceptionRecord->ExceptionCode ); + char addressString[32]; + sprintf_s( addressString, sizeof( addressString ), "0x%p", + excPointers->ExceptionRecord->ExceptionAddress ); + log() << "*** unhandled exception " << exceptionString + << " at " << addressString << ", terminating" << std::endl; + if ( excPointers->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION ) { + ULONG acType = excPointers->ExceptionRecord->ExceptionInformation[0]; + const char* acTypeString; + switch ( acType ) { + case 0: + acTypeString = "read from"; + break; + case 1: + acTypeString = "write to"; + break; + case 8: + acTypeString = "DEP violation at"; + break; + default: + acTypeString = "unknown violation at"; + break; + } + sprintf_s( addressString, sizeof( addressString ), " 0x%p", + excPointers->ExceptionRecord->ExceptionInformation[1] ); + log() << "*** access violation was a " << acTypeString << addressString << std::endl; + } + + log() << "*** stack trace for unhandled exception:" << std::endl; + printWindowsStackTrace( *excPointers->ContextRecord ); + doMinidump(excPointers); + + // Don't go through normal shutdown procedure. It may make things worse. + log() << "*** immediate exit due to unhandled exception" << std::endl; + ::_exit(EXIT_ABRUPT); + + // We won't reach here + return EXCEPTION_EXECUTE_HANDLER; + } + + LPTOP_LEVEL_EXCEPTION_FILTER filtLast = 0; + + void setWindowsUnhandledExceptionFilter() { + filtLast = SetUnhandledExceptionFilter(exceptionFilter); + } + +} // namespace mongo + +#else + +namespace mongo { + void setWindowsUnhandledExceptionFilter() { } +} + +#endif // _WIN32 |