Project

General

Profile

Bug #2695 » 0004-server.c-call-ftruncate-on-pid-file_patch.txt

mackyle, 2016-02-27 21:32

 
From 5b22648eef0000f28f9ddb9ce679e763d49352ed Mon Sep 17 00:00:00 2001
From: "Kyle J. McKay" <mackyle@gmail.com>
Date: Sat, 27 Feb 2016 13:23:48 -0800
Subject: [PATCH] server.c: call ftruncate on pid file

If the server has changed its uid or is running in a chroot
it may be unable to remove the pid file when it exits.

However, if it holds on to an open handle to the pid file
that has write permission, it will be able to truncate the
pid file to 0 bytes in length.

Most monitoring software recognizes a 0-length pid file
as indicating there is no process running.

Therefore always attempt to truncate the pid file before
trying to remove it so that it's not left containing the
pid of a process that is no longer running.

Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
---
src/server.c | 70 ++++++++++++++++++++++++++++++++++++------------------------
1 file changed, 42 insertions(+), 28 deletions(-)

diff --git a/src/server.c b/src/server.c
index dbbdb921..517a025e 100644
--- a/src/server.c
+++ b/src/server.c
@@ -356,6 +356,34 @@ static void server_free(server *srv) {
free(srv);
}
+static void remove_pid_file(server *srv, int *pid_fd) {
+ if (!buffer_string_is_empty(srv->srvconf.pid_file) && 0 <= *pid_fd) {
+ if (0 != ftruncate(*pid_fd, 0)) {
+ log_error_write(srv, __FILE__, __LINE__, "sbds",
+ "ftruncate failed for:",
+ srv->srvconf.pid_file,
+ errno,
+ strerror(errno));
+ }
+ }
+ if (0 <= *pid_fd) {
+ close(*pid_fd);
+ *pid_fd = -1;
+ }
+ if (!buffer_string_is_empty(srv->srvconf.pid_file) &&
+ buffer_string_is_empty(srv->srvconf.changeroot)) {
+ if (0 != unlink(srv->srvconf.pid_file->ptr)) {
+ if (errno != EACCES && errno != EPERM) {
+ log_error_write(srv, __FILE__, __LINE__, "sbds",
+ "unlink failed for:",
+ srv->srvconf.pid_file,
+ errno,
+ strerror(errno));
+ }
+ }
+ }
+}
+
static void show_version (void) {
#ifdef USE_OPENSSL
# define TEXT_SSL " (ssl)"
@@ -718,6 +746,7 @@ int main (int argc, char **argv) {
return -1;
}
}
+ fd_close_on_exec(pid_fd);
}
if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
@@ -1012,8 +1041,6 @@ int main (int argc, char **argv) {
close(pid_fd);
return -1;
}
- close(pid_fd);
- pid_fd = -1;
}
/* Close stderr ASAP in the child process to make sure that nothing
@@ -1146,6 +1173,7 @@ int main (int argc, char **argv) {
kill(0, SIGTERM);
}
+ remove_pid_file(srv, &pid_fd);
log_error_close(srv);
network_close(srv);
connections_free(srv);
@@ -1153,6 +1181,15 @@ int main (int argc, char **argv) {
server_free(srv);
return 0;
}
+
+ /**
+ * make sure workers do not muck with pid-file
+ */
+ if (0 <= pid_fd) {
+ close(pid_fd);
+ pid_fd = -1;
+ }
+ buffer_reset(srv->srvconf.pid_file);
}
#endif
@@ -1437,23 +1474,11 @@ int main (int argc, char **argv) {
srv_socket->fd = -1;
/* network_close() will cleanup after us */
-
- if (!buffer_string_is_empty(srv->srvconf.pid_file) &&
- buffer_string_is_empty(srv->srvconf.changeroot)) {
- if (0 != unlink(srv->srvconf.pid_file->ptr)) {
- if (errno != EACCES && errno != EPERM) {
- log_error_write(srv, __FILE__, __LINE__, "sbds",
- "unlink failed for:",
- srv->srvconf.pid_file,
- errno,
- strerror(errno));
- }
- }
- }
}
}
if (graceful_shutdown) {
+ remove_pid_file(srv, &pid_fd);
log_error_write(srv, __FILE__, __LINE__, "s", "[note] graceful shutdown started");
} else if (srv->conns->used >= srv->max_conns) {
log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets disabled, connection limit reached");
@@ -1555,19 +1580,8 @@ int main (int argc, char **argv) {
srv->joblist->used = 0;
}
- if (!buffer_string_is_empty(srv->srvconf.pid_file) &&
- buffer_string_is_empty(srv->srvconf.changeroot) &&
- 0 == graceful_shutdown) {
- if (0 != unlink(srv->srvconf.pid_file->ptr)) {
- if (errno != EACCES && errno != EPERM) {
- log_error_write(srv, __FILE__, __LINE__, "sbds",
- "unlink failed for:",
- srv->srvconf.pid_file,
- errno,
- strerror(errno));
- }
- }
- }
+ if (0 == graceful_shutdown)
+ remove_pid_file(srv, &pid_fd);
#ifdef HAVE_SIGACTION
log_error_write(srv, __FILE__, __LINE__, "sdsd",
--
2.6.5

(4-4/4)