diff options
author | Tad Marshall <tad@10gen.com> | 2012-06-10 16:12:08 -0400 |
---|---|---|
committer | Tad Marshall <tad@10gen.com> | 2012-06-10 16:12:08 -0400 |
commit | e1504ed07ff7c4b0f1c96da32c36ecf607ac0229 (patch) | |
tree | 3a53c99ec6b68b56de19d190a022a96c9471106a | |
parent | ef11f578a4cd48c72ea5eb4161adeab7c431b624 (diff) | |
download | mongo-e1504ed07ff7c4b0f1c96da32c36ecf607ac0229.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 0a21f4d19af..2a08ff3db3e 100644 --- a/db/db.cpp +++ b/db/db.cpp @@ -1154,31 +1154,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 1d5d58921d4..d51886dd9d8 100644 --- a/db/instance.cpp +++ b/db/instance.cpp @@ -874,6 +874,15 @@ namespace mongo { } catch (...) { } +#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); @@ -129,6 +129,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 4b21b8caecf..03c159ebe1d 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> @@ -348,14 +349,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; } } |