Project

General

Profile

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

mackyle, 2016-02-27 21:32

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

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

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

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

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

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

    
25
diff --git a/src/server.c b/src/server.c
26
index dbbdb921..517a025e 100644
27
--- a/src/server.c
28
+++ b/src/server.c
29
@@ -356,6 +356,34 @@ static void server_free(server *srv) {
30
 	free(srv);
31
 }
32
 
33
+static void remove_pid_file(server *srv, int *pid_fd) {
34
+	if (!buffer_string_is_empty(srv->srvconf.pid_file) && 0 <= *pid_fd) {
35
+		if (0 != ftruncate(*pid_fd, 0)) {
36
+			log_error_write(srv, __FILE__, __LINE__, "sbds",
37
+					"ftruncate failed for:",
38
+					srv->srvconf.pid_file,
39
+					errno,
40
+					strerror(errno));
41
+		}
42
+	}
43
+	if (0 <= *pid_fd) {
44
+		close(*pid_fd);
45
+		*pid_fd = -1;
46
+	}
47
+	if (!buffer_string_is_empty(srv->srvconf.pid_file) &&
48
+	    buffer_string_is_empty(srv->srvconf.changeroot)) {
49
+		if (0 != unlink(srv->srvconf.pid_file->ptr)) {
50
+			if (errno != EACCES && errno != EPERM) {
51
+				log_error_write(srv, __FILE__, __LINE__, "sbds",
52
+						"unlink failed for:",
53
+						srv->srvconf.pid_file,
54
+						errno,
55
+						strerror(errno));
56
+			}
57
+		}
58
+	}
59
+}
60
+
61
 static void show_version (void) {
62
 #ifdef USE_OPENSSL
63
 # define TEXT_SSL " (ssl)"
64
@@ -718,6 +746,7 @@ int main (int argc, char **argv) {
65
 				return -1;
66
 			}
67
 		}
68
+		fd_close_on_exec(pid_fd);
69
 	}
70
 
71
 	if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
72
@@ -1012,8 +1041,6 @@ int main (int argc, char **argv) {
73
 			close(pid_fd);
74
 			return -1;
75
 		}
76
-		close(pid_fd);
77
-		pid_fd = -1;
78
 	}
79
 
80
 	/* Close stderr ASAP in the child process to make sure that nothing
81
@@ -1146,6 +1173,7 @@ int main (int argc, char **argv) {
82
 				kill(0, SIGTERM);
83
 			}
84
 
85
+			remove_pid_file(srv, &pid_fd);
86
 			log_error_close(srv);
87
 			network_close(srv);
88
 			connections_free(srv);
89
@@ -1153,6 +1181,15 @@ int main (int argc, char **argv) {
90
 			server_free(srv);
91
 			return 0;
92
 		}
93
+
94
+		/**
95
+		 * make sure workers do not muck with pid-file
96
+		 */
97
+		if (0 <= pid_fd) {
98
+			close(pid_fd);
99
+			pid_fd = -1;
100
+		}
101
+		buffer_reset(srv->srvconf.pid_file);
102
 	}
103
 #endif
104
 
105
@@ -1437,23 +1474,11 @@ int main (int argc, char **argv) {
106
 						srv_socket->fd = -1;
107
 
108
 						/* network_close() will cleanup after us */
109
-
110
-						if (!buffer_string_is_empty(srv->srvconf.pid_file) &&
111
-						    buffer_string_is_empty(srv->srvconf.changeroot)) {
112
-							if (0 != unlink(srv->srvconf.pid_file->ptr)) {
113
-								if (errno != EACCES && errno != EPERM) {
114
-									log_error_write(srv, __FILE__, __LINE__, "sbds",
115
-											"unlink failed for:",
116
-											srv->srvconf.pid_file,
117
-											errno,
118
-											strerror(errno));
119
-								}
120
-							}
121
-						}
122
 					}
123
 				}
124
 
125
 				if (graceful_shutdown) {
126
+					remove_pid_file(srv, &pid_fd);
127
 					log_error_write(srv, __FILE__, __LINE__, "s", "[note] graceful shutdown started");
128
 				} else if (srv->conns->used >= srv->max_conns) {
129
 					log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets disabled, connection limit reached");
130
@@ -1555,19 +1580,8 @@ int main (int argc, char **argv) {
131
 		srv->joblist->used = 0;
132
 	}
133
 
134
-	if (!buffer_string_is_empty(srv->srvconf.pid_file) &&
135
-	    buffer_string_is_empty(srv->srvconf.changeroot) &&
136
-	    0 == graceful_shutdown) {
137
-		if (0 != unlink(srv->srvconf.pid_file->ptr)) {
138
-			if (errno != EACCES && errno != EPERM) {
139
-				log_error_write(srv, __FILE__, __LINE__, "sbds",
140
-						"unlink failed for:",
141
-						srv->srvconf.pid_file,
142
-						errno,
143
-						strerror(errno));
144
-			}
145
-		}
146
-	}
147
+	if (0 == graceful_shutdown)
148
+		remove_pid_file(srv, &pid_fd);
149
 
150
 #ifdef HAVE_SIGACTION
151
 	log_error_write(srv, __FILE__, __LINE__, "sdsd", 
152
-- 
153
2.6.5
154

    
(4-4/4)