summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTad Marshall <tad@10gen.com>2011-12-01 20:42:13 -0500
committerTad Marshall <tad@10gen.com>2011-12-01 20:42:13 -0500
commitc8e45cce25d4de4e877e8179f21d8c93166bc964 (patch)
tree0e8fb5c598adebae0280490f8f6edfaf8b21b3ba
parentc6228e1970fc436602b5ea1f317e3cb7588d516b (diff)
downloadmongo-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.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 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);
diff --git a/pch.h b/pch.h
index 600d41648e2..28d462e85b3 100644
--- a/pch.h
+++ b/pch.h
@@ -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;
}
}