summaryrefslogtreecommitdiff
path: root/src
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
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')
-rw-r--r--src/mongo/SConscript1
-rw-r--r--src/mongo/db/db.cpp99
-rw-r--r--src/mongo/s/server.cpp2
-rw-r--r--src/mongo/util/exception_filter_win32.cpp130
-rw-r--r--src/mongo/util/exception_filter_win32.h23
5 files changed, 162 insertions, 93 deletions
diff --git a/src/mongo/SConscript b/src/mongo/SConscript
index 7a080887cd0..175337acccc 100644
--- a/src/mongo/SConscript
+++ b/src/mongo/SConscript
@@ -30,6 +30,7 @@ env.StaticLibrary('foundation',
[ 'util/assert_util.cpp',
'util/concurrency/mutexdebugger.cpp',
'util/debug_util.cpp',
+ 'util/exception_filter_win32.cpp',
'util/log.cpp',
'util/signal_handlers.cpp',
'util/text.cpp',
diff --git a/src/mongo/db/db.cpp b/src/mongo/db/db.cpp
index bb2b8ba7aad..0b82d08383b 100644
--- a/src/mongo/db/db.cpp
+++ b/src/mongo/db/db.cpp
@@ -52,6 +52,7 @@
#include "mongo/scripting/engine.h"
#include "mongo/util/background.h"
#include "mongo/util/concurrency/task.h"
+#include "mongo/util/exception_filter_win32.h"
#include "mongo/util/file_allocator.h"
#include "mongo/util/net/message_server.h"
#include "mongo/util/ntservice.h"
@@ -61,9 +62,7 @@
#include "mongo/util/text.h"
#include "mongo/util/version.h"
-#if defined(_WIN32)
-# include <DbgHelp.h>
-#else
+#if !defined(_WIN32)
# include <sys/file.h>
#endif
@@ -1420,94 +1419,6 @@ namespace mongo {
}
}
- LPTOP_LEVEL_EXCEPTION_FILTER filtLast = 0;
-
- /* 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 ) << endl;
- return;
- }
-
- MINIDUMP_EXCEPTION_INFORMATION aMiniDumpInfo;
- aMiniDumpInfo.ThreadId = GetCurrentThreadId();
- aMiniDumpInfo.ExceptionPointers = exceptionInfo;
- aMiniDumpInfo.ClientPointers = TRUE;
-
- log() << "writing minidump diagnostic file " << toUtf8String(dumpFilename) << endl;
- BOOL bstatus = MiniDumpWriteDump(GetCurrentProcess(),
- GetCurrentProcessId(),
- hFile,
- MiniDumpNormal,
- &aMiniDumpInfo,
- NULL,
- NULL);
- if ( FALSE == bstatus ) {
- DWORD lasterr = GetLastError();
- log() << "failed to create minidump : "
- << errnoWithDescription( lasterr ) << 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" << 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 << endl;
- }
-
- log() << "*** stack trace for unhandled exception:" << 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" << endl;
- ::_exit(EXIT_ABRUPT);
-
- // We won't reach here
- return EXCEPTION_EXECUTE_HANDLER;
- }
-
// called by mongoAbort()
extern void (*reportEventToSystem)(const char *msg);
void reportEventToSystemImpl(const char *msg) {
@@ -1533,8 +1444,10 @@ namespace mongo {
void setupSignals( bool inFork ) {
reportEventToSystem = reportEventToSystemImpl;
- filtLast = SetUnhandledExceptionFilter(exceptionFilter);
- massert(10297 , "Couldn't register Windows Ctrl-C handler", SetConsoleCtrlHandler((PHANDLER_ROUTINE) CtrlHandler, TRUE));
+ setWindowsUnhandledExceptionFilter();
+ massert(10297,
+ "Couldn't register Windows Ctrl-C handler",
+ SetConsoleCtrlHandler(static_cast<PHANDLER_ROUTINE>(CtrlHandler), TRUE));
_set_purecall_handler( myPurecallHandler );
}
diff --git a/src/mongo/s/server.cpp b/src/mongo/s/server.cpp
index 3262a11036c..265a97682c8 100644
--- a/src/mongo/s/server.cpp
+++ b/src/mongo/s/server.cpp
@@ -48,6 +48,7 @@
#include "../util/processinfo.h"
#include "mongo/db/lasterror.h"
#include "mongo/util/stacktrace.h"
+#include "mongo/util/exception_filter_win32.h"
#if defined(_WIN32)
# include "../util/ntservice.h"
@@ -176,6 +177,7 @@ namespace mongo {
signal( SIGPIPE , SIG_IGN );
#endif
+ setWindowsUnhandledExceptionFilter();
set_new_handler( my_new_handler );
}
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
diff --git a/src/mongo/util/exception_filter_win32.h b/src/mongo/util/exception_filter_win32.h
new file mode 100644
index 00000000000..e8798887bdd
--- /dev/null
+++ b/src/mongo/util/exception_filter_win32.h
@@ -0,0 +1,23 @@
+/**
+* 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/>.
+*/
+
+#pragma once
+
+namespace mongo {
+
+ void setWindowsUnhandledExceptionFilter();
+
+} // namespace mongo