void eventProcessingThread() { std::string eventName = getShutdownSignalName(ProcessId::getCurrent().asUInt32()); HANDLE event = CreateEventA(NULL, TRUE, FALSE, eventName.c_str()); if (event == NULL) { warning() << "eventProcessingThread CreateEvent failed: " << errnoWithDescription(); return; } ON_BLOCK_EXIT(CloseHandle, event); int returnCode = WaitForSingleObject(event, INFINITE); if (returnCode != WAIT_OBJECT_0) { if (returnCode == WAIT_FAILED) { warning() << "eventProcessingThread WaitForSingleObject failed: " << errnoWithDescription(); return; } else { warning() << "eventProcessingThread WaitForSingleObject failed: " << errnoWithDescription(returnCode); return; } } Client::initThread("eventTerminate"); log() << "shutdown event signaled, will terminate after current cmd ends"; exitCleanly(EXIT_CLEAN); }
inline void kill_wrapper( ProcessId pid, int sig, int port, const BSONObj& opt ) { #ifdef _WIN32 if (sig == SIGKILL || port == 0) { verify( registry._handles.count(pid) ); TerminateProcess(registry._handles[pid], 1); // returns failure for "zombie" processes. return; } std::string eventName = getShutdownSignalName(pid.asUInt32()); HANDLE event = OpenEventA(EVENT_MODIFY_STATE, FALSE, eventName.c_str()); if (event == NULL) { int gle = GetLastError(); if (gle != ERROR_FILE_NOT_FOUND) { warning() << "kill_wrapper OpenEvent failed: " << errnoWithDescription(); } else { log() << "kill_wrapper OpenEvent failed to open event to the process " << pid.asUInt32() << ". It has likely died already"; } return; } ON_BLOCK_EXIT(CloseHandle, event); bool result = SetEvent(event); if (!result) { error() << "kill_wrapper SetEvent failed: " << errnoWithDescription(); return; } #else int x = kill( pid.toNative(), sig ); if ( x ) { if ( errno == ESRCH ) { } else { log() << "killFailed: " << errnoWithDescription() << endl; verify( x == 0 ); } } #endif }
inline void kill_wrapper( ProcessId pid, int sig, int port, const BSONObj& opt ) { #ifdef _WIN32 if (sig == SIGKILL || port == 0) { verify( registry._handles.count(pid) ); TerminateProcess(registry._handles[pid], 1); // returns failure for "zombie" processes. return; } std::string eventName = getShutdownSignalName(pid.asUInt32()); HANDLE event = OpenEventA(EVENT_MODIFY_STATE, FALSE, eventName.c_str()); if (event == NULL) { int gle = GetLastError(); if (gle != ERROR_FILE_NOT_FOUND) { warning() << "kill_wrapper OpenEvent failed: " << errnoWithDescription(); } else { log() << "kill_wrapper OpenEvent failed to open event to the process " << pid.asUInt32() << ". It has likely died already or server is running an older version." << " Attempting to shutdown through admin command."; // Back-off to the old way of shutting down the server on Windows, in case we // are managing a pre-2.6.0rc0 service, which did not have the event. // try { DBClientConnection conn; conn.connect("127.0.0.1:" + BSONObjBuilder::numStr(port)); BSONElement authObj = opt["auth"]; if (!authObj.eoo()){ string errMsg; conn.auth("admin", authObj["user"].String(), authObj["pwd"].String(), errMsg); if (!errMsg.empty()) { cout << "Failed to authenticate before shutdown: " << errMsg << endl; } } BSONObj info; BSONObjBuilder b; b.append("shutdown", 1); b.append("force", 1); conn.runCommand("admin", b.done(), info); } catch (...) { // Do nothing. This command never returns data to the client and the driver // doesn't like that. // } } return; } ON_BLOCK_EXIT(CloseHandle, event); bool result = SetEvent(event); if (!result) { error() << "kill_wrapper SetEvent failed: " << errnoWithDescription(); return; } #else int x = kill( pid.toNative(), sig ); if ( x ) { if ( errno == ESRCH ) { } else { log() << "killFailed: " << errnoWithDescription() << endl; verify( x == 0 ); } } #endif }