summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTad Marshall <tad@10gen.com>2012-06-10 16:12:08 -0400
committerTad Marshall <tad@10gen.com>2012-06-10 16:12:08 -0400
commite1504ed07ff7c4b0f1c96da32c36ecf607ac0229 (patch)
tree3a53c99ec6b68b56de19d190a022a96c9471106a
parentef11f578a4cd48c72ea5eb4161adeab7c431b624 (diff)
downloadmongo-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.cpp40
-rw-r--r--db/instance.cpp9
-rw-r--r--pch.h1
-rw-r--r--util/ntservice.cpp20
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);
diff --git a/pch.h b/pch.h
index 1211e26adc6..6cf2f462876 100644
--- a/pch.h
+++ b/pch.h
@@ -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;
}
}