summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Benvenuto <mark.benvenuto@mongodb.com>2015-08-10 14:00:41 -0400
committerMark Benvenuto <mark.benvenuto@mongodb.com>2015-08-13 10:17:56 -0400
commit1e9821f9177dc5d8602d9f41b38edc0b0269fb6c (patch)
treea64e545aafd77876b4240d784f061e48df02b1ee
parent7397477c45986e2a9ed195f912afee3ed9ffcbc7 (diff)
downloadmongo-1e9821f9177dc5d8602d9f41b38edc0b0269fb6c.tar.gz
SERVER-19856: Register for PRESHUTDOWN notifications on Windows Vista+
(cherry picked from commit a694a774259e44024697f4763784b59b2ba8b85d)
-rw-r--r--src/mongo/util/ntservice.cpp43
1 files changed, 34 insertions, 9 deletions
diff --git a/src/mongo/util/ntservice.cpp b/src/mongo/util/ntservice.cpp
index 751f9870fe5..e1098d7fd24 100644
--- a/src/mongo/util/ntservice.cpp
+++ b/src/mongo/util/ntservice.cpp
@@ -75,7 +75,8 @@ bool shouldStartService() {
return _startService;
}
-static void WINAPI serviceCtrl(DWORD ctrlCode);
+static DWORD WINAPI
+serviceCtrl(DWORD dwControl, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext);
void configureService(ServiceCallback serviceCallback,
const moe::Environment& params,
@@ -408,6 +409,21 @@ void installServiceOrDie(const wstring& serviceName,
log() << "Could not set service description. Check the Windows Event Log for more details.";
}
+ // Set the pre-shutdown notification with a timeout of 10 minutes.
+ // Windows will either wait for us to finish with SERVICE_STOPPED or it will timeout, whichever
+ // is first.
+ SERVICE_PRESHUTDOWN_INFO servicePreshutdownInfo;
+ servicePreshutdownInfo.dwPreshutdownTimeout = 10 * 60 * 1000; // 10 minutes
+
+ BOOL ret = ::ChangeServiceConfig2(
+ schService, SERVICE_CONFIG_PRESHUTDOWN_INFO, &servicePreshutdownInfo);
+ if (!ret) {
+ DWORD gle = ::GetLastError();
+ error() << "Failed to set timeout for pre-shutdown notification with error: "
+ << errnoWithDescription(gle);
+ serviceInstalled = false;
+ }
+
::CloseServiceHandle(schService);
::CloseServiceHandle(schSCManager);
@@ -479,7 +495,7 @@ bool reportStatus(DWORD reportState, DWORD waitHint, DWORD exitCode) {
dwControlsAccepted = 0;
break;
default:
- dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
+ dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PRESHUTDOWN;
break;
}
@@ -530,7 +546,7 @@ static void serviceStop() {
}
static void WINAPI initService(DWORD argc, LPTSTR* argv) {
- _statusHandle = RegisterServiceCtrlHandler(_serviceName.c_str(), serviceCtrl);
+ _statusHandle = RegisterServiceCtrlHandlerEx(_serviceName.c_str(), serviceCtrl, NULL);
if (!_statusHandle)
return;
@@ -562,15 +578,24 @@ static void serviceShutdown(const char* controlCodeName) {
// Note: we will report exit status in initService
}
-static void WINAPI serviceCtrl(DWORD ctrlCode) {
- switch (ctrlCode) {
+static DWORD WINAPI
+serviceCtrl(DWORD dwControl, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext) {
+ switch (dwControl) {
+ case SERVICE_CONTROL_INTERROGATE:
+ // Return NO_ERROR per MSDN even though we do nothing for this control code.
+ return NO_ERROR;
case SERVICE_CONTROL_STOP:
serviceShutdown("SERVICE_CONTROL_STOP");
- break;
- case SERVICE_CONTROL_SHUTDOWN:
- serviceShutdown("SERVICE_CONTROL_SHUTDOWN");
- break;
+ // Return NO_ERROR since we handle the STOP
+ return NO_ERROR;
+ case SERVICE_CONTROL_PRESHUTDOWN:
+ serviceShutdown("SERVICE_CONTROL_PRESHUTDOWN");
+ // Return NO_ERROR since we handle the PRESHUTDOWN
+ return NO_ERROR;
}
+
+ // Return ERROR_CALL_NOT_IMPLEMENTED as the default
+ return ERROR_CALL_NOT_IMPLEMENTED;
}
void startService() {