summaryrefslogtreecommitdiff
path: root/src/mongo/util/exception_filter_win32.cpp
diff options
context:
space:
mode:
authorTad Marshall <tad@10gen.com>2012-12-07 08:03:45 -0500
committerTad Marshall <tad@10gen.com>2012-12-07 11:21:01 -0500
commit90440532fca3ce59383ad7e36437191f4819b3fc (patch)
tree5373b1f780a019ac5856a5e35a8bd9a64e4888f7 /src/mongo/util/exception_filter_win32.cpp
parent9fe63411b92a2469d364f4678f04830fdc9e4a38 (diff)
downloadmongo-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.cpp130
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