summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorMark Benvenuto <mark.benvenuto@mongodb.com>2015-04-01 13:58:50 -0400
committerMark Benvenuto <mark.benvenuto@mongodb.com>2015-04-03 11:06:07 -0400
commit7060c72b30a836b3052f7890ea8c4b592014adf4 (patch)
tree13ea248852abe88abfa7b30808e271d35942b072 /src/mongo
parentfe358a4fd67fc48188eb062ae026001ff74082e9 (diff)
downloadmongo-7060c72b30a836b3052f7890ea8c4b592014adf4.tar.gz
SERVER-17820: Handle long running exitCleanly in Service Stop
Diffstat (limited to 'src/mongo')
-rw-r--r--src/mongo/util/ntservice.cpp35
1 files changed, 30 insertions, 5 deletions
diff --git a/src/mongo/util/ntservice.cpp b/src/mongo/util/ntservice.cpp
index 8e8b66a2179..7aafb2681fb 100644
--- a/src/mongo/util/ntservice.cpp
+++ b/src/mongo/util/ntservice.cpp
@@ -514,6 +514,34 @@ namespace {
return SetServiceStatus( _statusHandle, &ssStatus );
}
+ static void serviceStopWorker() {
+ Client::initThread("serviceStopWorker");
+
+ // Stop the process
+ // TODO: SERVER-5703, separate the "cleanup for shutdown" functionality from
+ // the "terminate process" functionality in exitCleanly.
+ exitCleanly(EXIT_WINDOWS_SERVICE_STOP);
+ }
+
+ // Minimum of time we tell Windows to wait before we are guilty of a hung shutdown
+ const int kStopWaitHintMillis = 30000;
+
+ // Run exitCleanly on a separate thread so we can report progress to Windows
+ // Note: Windows may still kill us for taking too long,
+ // On client OSes, SERVICE_CONTROL_SHUTDOWN has a 5 second timeout configured in
+ // HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control
+ static void serviceStop() {
+ boost::thread serviceWorkerThread(serviceStopWorker);
+
+ // We periodically check if we are done exiting by polling at half of each wait interval
+ //
+ while (!serviceWorkerThread.try_join_for(
+ boost::chrono::milliseconds(kStopWaitHintMillis / 2))) {
+ reportStatus(SERVICE_STOP_PENDING, kStopWaitHintMillis);
+ log() << "Service Stop is waiting for storage engine to finish shutdown";
+ }
+ }
+
static void WINAPI initService( DWORD argc, LPTSTR *argv ) {
_statusHandle = RegisterServiceCtrlHandler( _serviceName.c_str(), serviceCtrl );
if ( !_statusHandle )
@@ -523,14 +551,11 @@ namespace {
ExitCode exitCode = _serviceCallback();
- // Stop the process
// During clean shutdown, ie NT SCM signals us, _serviceCallback returns here
// as part of the listener loop terminating.
// exitCleanly is supposed to return. If it blocks, some other thread must be exiting.
//
- // TODO: SERVER-5703, separate the "cleanup for shutdown" functionality from
- // the "terminate process" functionality in exitCleanly.
- exitCleanly( EXIT_WINDOWS_SERVICE_STOP );
+ serviceStop();
reportStatus(SERVICE_STOPPED, 0, exitCode);
}
@@ -541,7 +566,7 @@ namespace {
log() << "got " << controlCodeName << " request from Windows Service Control Manager, " <<
( inShutdown() ? "already in shutdown" : "will terminate after current cmd ends" );
- reportStatus( SERVICE_STOP_PENDING );
+ reportStatus(SERVICE_STOP_PENDING, kStopWaitHintMillis);
// Note: This triggers _serviceCallback, ie ServiceMain,
// to stop by setting inShutdown() == true