nghttpx: Write PID in temporary file then rename
Write PID in temporary file first. Then rename it as the real destination. It will avoid the issue that the external process may read the empty PID file because of race condition.
This commit is contained in:
parent
65135bc319
commit
c308be39de
54
src/shrpx.cc
54
src/shrpx.cc
|
@ -200,18 +200,58 @@ int chown_to_running_user(const char *path) {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
void save_pid() {
|
void save_pid() {
|
||||||
std::ofstream out(get_config()->pid_file.c_str(), std::ios::binary);
|
constexpr auto SUFFIX = StringRef::from_lit(".XXXXXX");
|
||||||
out << get_config()->pid << "\n";
|
auto &pid_file = get_config()->pid_file;
|
||||||
out.close();
|
|
||||||
if (!out) {
|
std::vector<char> temp_path;
|
||||||
LOG(ERROR) << "Could not save PID to file " << get_config()->pid_file;
|
temp_path.reserve(get_config()->pid_file.size() + SUFFIX.size() + 1);
|
||||||
|
|
||||||
|
auto p = std::copy(std::begin(pid_file), std::end(pid_file),
|
||||||
|
std::begin(temp_path));
|
||||||
|
|
||||||
|
p = std::copy(std::begin(SUFFIX), std::end(SUFFIX), p);
|
||||||
|
*p = '\0';
|
||||||
|
|
||||||
|
auto fd = mkstemp(temp_path.data());
|
||||||
|
if (fd == -1) {
|
||||||
|
auto error = errno;
|
||||||
|
LOG(ERROR) << "Could not save PID to file " << pid_file << ": "
|
||||||
|
<< strerror(error);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto content = util::utos(get_config()->pid) + '\n';
|
||||||
|
|
||||||
|
if (write(fd, content.c_str(), content.size()) == -1) {
|
||||||
|
auto error = errno;
|
||||||
|
LOG(ERROR) << "Could not save PID to file " << pid_file << ": "
|
||||||
|
<< strerror(error);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fsync(fd) == -1) {
|
||||||
|
auto error = errno;
|
||||||
|
LOG(ERROR) << "Could not save PID to file " << pid_file << ": "
|
||||||
|
<< strerror(error);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
if (rename(temp_path.data(), pid_file.c_str()) == -1) {
|
||||||
|
auto error = errno;
|
||||||
|
LOG(ERROR) << "Could not save PID to file " << pid_file << ": "
|
||||||
|
<< strerror(error);
|
||||||
|
|
||||||
|
unlink(temp_path.data());
|
||||||
|
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_config()->uid != 0) {
|
if (get_config()->uid != 0) {
|
||||||
if (chown_to_running_user(get_config()->pid_file.c_str()) == -1) {
|
if (chown_to_running_user(pid_file.c_str()) == -1) {
|
||||||
auto error = errno;
|
auto error = errno;
|
||||||
LOG(WARN) << "Changing owner of pid file " << get_config()->pid_file
|
LOG(WARN) << "Changing owner of pid file " << pid_file
|
||||||
<< " failed: " << strerror(error);
|
<< " failed: " << strerror(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue