diff options
author | Sara Golemon <sara.golemon@mongodb.com> | 2021-05-11 17:01:57 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2021-05-26 07:34:50 +0000 |
commit | a07dc78e49c53de539dff92748334cd7fbe2e2a9 (patch) | |
tree | 4a4ce1c5e77e4068d0d0226f7f68570409600f49 /src/mongo/db/mongod_main.cpp | |
parent | da10c9aff0b4f1dface979ddd0605e6d142488c5 (diff) | |
download | mongo-a07dc78e49c53de539dff92748334cd7fbe2e2a9.tar.gz |
SERVER-56677 Refactor --shutdown handling
Diffstat (limited to 'src/mongo/db/mongod_main.cpp')
-rw-r--r-- | src/mongo/db/mongod_main.cpp | 99 |
1 files changed, 60 insertions, 39 deletions
diff --git a/src/mongo/db/mongod_main.cpp b/src/mongo/db/mongod_main.cpp index 54b3f7f70bd..a3879a152c6 100644 --- a/src/mongo/db/mongod_main.cpp +++ b/src/mongo/db/mongod_main.cpp @@ -842,6 +842,63 @@ MONGO_INITIALIZER_GENERAL(ForkServer, ("EndStartupOptionHandling"), ("default")) mongo::forkServerOrDie(); } +#ifdef __linux__ +/** + * Read the pid file from the dbpath for the process ID used by this instance of the server. + * Use that process number to kill the running server. + * + * Equivalent to: `kill -SIGTERM $(cat $DBPATH/mongod.lock)` + * + * Performs additional checks to make sure the PID as read is reasonable (>= 1) + * and can be found in the /proc filesystem. + */ +Status shutdownProcessByDBPathPidFile(const std::string& dbpath) { + auto pidfile = (boost::filesystem::path(dbpath) / kLockFileBasename.toString()).string(); + if (!boost::filesystem::exists(pidfile)) { + return {ErrorCodes::OperationFailed, + str::stream() << "There doesn't seem to be a server running with dbpath: " + << dbpath}; + } + + pid_t pid; + try { + std::ifstream f(pidfile.c_str()); + f >> pid; + } catch (const std::exception& ex) { + return {ErrorCodes::OperationFailed, + str::stream() << "Error reading pid from lock file [" << pidfile + << "]: " << ex.what()}; + } + + if (pid <= 0) { + return {ErrorCodes::OperationFailed, + str::stream() << "Invalid process ID '" << pid + << "' read from pidfile: " << pidfile}; + } + + std::string procPath = str::stream() << "/proc/" << pid; + if (!boost::filesystem::exists(procPath)) { + return {ErrorCodes::OperationFailed, + str::stream() << "Process ID '" << pid << "' read from pidfile '" << pidfile + << "' does not appear to be running"}; + } + + std::cout << "Killing process with pid: " << pid << std::endl; + int ret = kill(pid, SIGTERM); + if (ret) { + int e = errno; + return {ErrorCodes::OperationFailed, + str::stream() << "Failed to kill process: " << errnoWithDescription(e)}; + } + + while (boost::filesystem::exists(pidfile)) { + sleepsecs(1); + } + + return Status::OK(); +} +#endif // __linux__ + /* * This function should contain the startup "actions" that we take based on the startup config. * It is intended to separate the actions from "storage" and "validation" of our startup @@ -883,48 +940,12 @@ void startupConfigActions(const std::vector<std::string>& args) { #ifdef __linux__ if (moe::startupOptionsParsed.count("shutdown") && moe::startupOptionsParsed["shutdown"].as<bool>() == true) { - bool failed = false; - - std::string name = - (boost::filesystem::path(storageGlobalParams.dbpath) / kLockFileBasename.toString()) - .string(); - if (!boost::filesystem::exists(name) || boost::filesystem::file_size(name) == 0) - failed = true; - - pid_t pid; - std::string procPath; - if (!failed) { - try { - std::ifstream f(name.c_str()); - f >> pid; - procPath = (str::stream() << "/proc/" << pid); - if (!boost::filesystem::exists(procPath)) - failed = true; - } catch (const std::exception& e) { - std::cerr << "Error reading pid from lock file [" << name << "]: " << e.what() - << endl; - failed = true; - } - } - - if (failed) { - std::cerr << "There doesn't seem to be a server running with dbpath: " - << storageGlobalParams.dbpath << std::endl; - quickExit(EXIT_FAILURE); - } - - std::cout << "killing process with pid: " << pid << endl; - int ret = kill(pid, SIGTERM); - if (ret) { - int e = errno; - std::cerr << "failed to kill process: " << errnoWithDescription(e) << endl; + auto status = shutdownProcessByDBPathPidFile(storageGlobalParams.dbpath); + if (!status.isOK()) { + std::cerr << status.reason() << std::endl; quickExit(EXIT_FAILURE); } - while (boost::filesystem::exists(procPath)) { - sleepsecs(1); - } - quickExit(EXIT_SUCCESS); } #endif |