From 3fdb9db0c1662abafa5de3005ad9a23b289bc8a0 Mon Sep 17 00:00:00 2001 From: "Kyle J. McKay" Date: Fri, 4 Dec 2015 16:45:25 -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 --- src/server.c | 56 +++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 15 deletions(-) diff --git a/src/server.c b/src/server.c index c5845e2c..2764c9a5 100644 --- a/src/server.c +++ b/src/server.c @@ -718,6 +718,7 @@ int main (int argc, char **argv) { return -1; } } + fd_close_on_exec(pid_fd); } if (srv->event_handler == FDEVENT_HANDLER_SELECT) { @@ -1012,8 +1013,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 @@ -1437,23 +1436,36 @@ 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) { + 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)); + } + } + } 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"); @@ -1556,6 +1568,20 @@ int main (int argc, char **argv) { } if (!buffer_string_is_empty(srv->srvconf.pid_file) && + 0 == graceful_shutdown && 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) && 0 == graceful_shutdown) { if (0 != unlink(srv->srvconf.pid_file->ptr)) { -- 2.4.10