diff options
author | Tad Marshall <tad@10gen.com> | 2011-12-01 20:42:13 -0500 |
---|---|---|
committer | Tad Marshall <tad@10gen.com> | 2011-12-01 20:42:13 -0500 |
commit | c8e45cce25d4de4e877e8179f21d8c93166bc964 (patch) | |
tree | 0e8fb5c598adebae0280490f8f6edfaf8b21b3ba | |
parent | c6228e1970fc436602b5ea1f317e3cb7588d516b (diff) | |
download | mongo-c8e45cce25d4de4e877e8179f21d8c93166bc964.tar.gz |
SERVER-2833 -- shut down cleanly on OS or Service Controller shutdown event
Added code to log shutdown events from the Windows Service Controller
and to respond correctly to those events. Shutdown from the console
on logoff or shutdown callbacks (stop ignoring them).
-rw-r--r-- | db/db.cpp | 40 | ||||
-rw-r--r-- | db/instance.cpp | 9 | ||||
-rw-r--r-- | pch.h | 1 | ||||
-rw-r--r-- | util/ntservice.cpp | 20 |
4 files changed, 51 insertions, 19 deletions
diff --git a/db/db.cpp b/db/db.cpp index ebedbacd29a..4c6b79595e8 100644 --- a/db/db.cpp +++ b/db/db.cpp @@ -1205,31 +1205,41 @@ namespace mongo { } #else - void ctrlCTerminate() { - log() << "got kill or ctrl-c signal, will terminate after current cmd ends" << endl; - Client::initThread( "ctrlCTerminate" ); + void consoleTerminate( const char* controlCodeName ) { + Client::initThread( "consoleTerminate" ); + log() << "got " << controlCodeName << ", will terminate after current cmd ends" << endl; exitCleanly( EXIT_KILL ); } + BOOL CtrlHandler( DWORD fdwCtrlType ) { + switch( fdwCtrlType ) { + case CTRL_C_EVENT: - rawOut("Ctrl-C signal"); - ctrlCTerminate(); - return( TRUE ); + rawOut( "Ctrl-C signal" ); + consoleTerminate( "CTRL_C_EVENT" ); + return TRUE ; + case CTRL_CLOSE_EVENT: - rawOut("CTRL_CLOSE_EVENT signal"); - ctrlCTerminate(); - return( TRUE ); + rawOut( "CTRL_CLOSE_EVENT signal" ); + consoleTerminate( "CTRL_CLOSE_EVENT" ); + return TRUE ; + case CTRL_BREAK_EVENT: - rawOut("CTRL_BREAK_EVENT signal"); - ctrlCTerminate(); + rawOut( "CTRL_BREAK_EVENT signal" ); + consoleTerminate( "CTRL_BREAK_EVENT" ); return TRUE; + case CTRL_LOGOFF_EVENT: - rawOut("CTRL_LOGOFF_EVENT signal (ignored)"); - return FALSE; + rawOut( "CTRL_LOGOFF_EVENT signal" ); + consoleTerminate( "CTRL_LOGOFF_EVENT" ); + return TRUE; + case CTRL_SHUTDOWN_EVENT: - rawOut("CTRL_SHUTDOWN_EVENT signal (ignored)"); - return FALSE; + rawOut( "CTRL_SHUTDOWN_EVENT signal" ); + consoleTerminate( "CTRL_SHUTDOWN_EVENT" ); + return TRUE; + default: return FALSE; } diff --git a/db/instance.cpp b/db/instance.cpp index 09543bda4db..0b3953e4d6e 100644 --- a/db/instance.cpp +++ b/db/instance.cpp @@ -927,6 +927,15 @@ namespace mongo { catch (...) { } #endif +#ifdef _WIN32 + // Windows Service Controller wants to be told when we are down, + // so don't call ::exit() yet, or say "really exiting now" + // + if ( rc == EXIT_WINDOWS_SERVICE_STOP ) { + if ( c ) c->shutdown(); + return; + } +#endif tryToOutputFatal( "dbexit: really exiting now" ); if ( c ) c->shutdown(); ::exit(rc); @@ -131,6 +131,7 @@ namespace mongo { EXIT_FS = 45 , EXIT_CLOCK_SKEW = 47 , EXIT_NET_ERROR = 48 , + EXIT_WINDOWS_SERVICE_STOP = 49 , EXIT_POSSIBLE_CORRUPTION = 60 , // this means we detected a possible corruption situation, like a buf overflow EXIT_UNCAUGHT = 100 , // top level exception that wasn't caught EXIT_TEST = 101 , diff --git a/util/ntservice.cpp b/util/ntservice.cpp index d5171233ca9..cdeaeda0f3f 100644 --- a/util/ntservice.cpp +++ b/util/ntservice.cpp @@ -17,6 +17,7 @@ #include "pch.h" #include "ntservice.h" +#include "../db/client.h" #include "winutil.h" #include "text.h" #include <direct.h> @@ -355,14 +356,25 @@ namespace mongo { reportStatus( SERVICE_STOPPED ); } + static void serviceShutdown( const char* controlCodeName ) { + Client::initThread( "serviceShutdown" ); + log() << "got " << controlCodeName << " request from Windows Service Controller, " << + ( inShutdown() ? "already in shutdown" : "will terminate after current cmd ends" ) << endl; + ServiceController::reportStatus( SERVICE_STOP_PENDING ); + if ( ! inShutdown() ) { + exitCleanly( EXIT_WINDOWS_SERVICE_STOP ); + ServiceController::reportStatus( SERVICE_STOPPED ); + } + } + void WINAPI ServiceController::serviceCtrl( DWORD ctrlCode ) { switch ( ctrlCode ) { case SERVICE_CONTROL_STOP: + serviceShutdown( "SERVICE_CONTROL_STOP" ); + break; case SERVICE_CONTROL_SHUTDOWN: - reportStatus( SERVICE_STOP_PENDING ); - shutdownServer(); - reportStatus( SERVICE_STOPPED ); - return; + serviceShutdown( "SERVICE_CONTROL_SHUTDOWN" ); + break; } } |