summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorstbuehler <stbuehler@152afb58-edef-0310-8abb-c4023f1b3aa9>2016-03-19 15:01:23 +0000
committerstbuehler <stbuehler@152afb58-edef-0310-8abb-c4023f1b3aa9>2016-03-19 15:01:23 +0000
commite3025dbc6495fe929eab17392b266f0cfd3bb633 (patch)
treef36ea9807c23ef190e70ffd9a407347a42f44ec2
parent3d4075dd07f7bd93c5189e5795dd37e4fe1ebb3a (diff)
downloadlighttpd-e3025dbc6495fe929eab17392b266f0cfd3bb633.tar.gz
[core] truncate pidfile on exit (fixes #2695)
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> git-svn-id: svn://svn.lighttpd.net/lighttpd/branches/lighttpd-1.4.x@3112 152afb58-edef-0310-8abb-c4023f1b3aa9
-rw-r--r--NEWS1
-rw-r--r--src/server.c69
2 files changed, 43 insertions, 27 deletions
diff --git a/NEWS b/NEWS
index 4cbcf442..0742720f 100644
--- a/NEWS
+++ b/NEWS
@@ -40,6 +40,7 @@ NEWS
* [core] log remote address on request timeouts (fixes #652)
* [autobuild] use AC_CANONICAL_HOST instead of AC_CANONICAL_TARGET (fixes #1866)
* [core] fix request_start in keep-alive requests to mark time when received first byte (fixes #2412)
+ * [core] truncate pidfile on exit (fixes #2695)
- 1.4.39 - 2016-01-02
* [core] fix memset_s call (fixes #2698)
diff --git a/src/server.c b/src/server.c
index ffb22038..0218cd24 100644
--- a/src/server.c
+++ b/src/server.c
@@ -355,6 +355,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)"
@@ -717,6 +745,7 @@ int main (int argc, char **argv) {
return -1;
}
}
+ fd_close_on_exec(pid_fd);
}
if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
@@ -1014,8 +1043,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
@@ -1148,6 +1175,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);
@@ -1155,6 +1183,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
@@ -1441,23 +1478,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");
@@ -1559,18 +1584,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