Project

General

Profile

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

mackyle, 2015-12-05 02:19

 
1
From c63a20c1fe9c34af08c24d141e8bb81bcf2e40b6 Mon Sep 17 00:00:00 2001
2
From: "Kyle J. McKay" <mackyle@gmail.com>
3
Date: Fri, 4 Dec 2015 18:10:45 -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 | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++----------
23
 1 file changed, 76 insertions(+), 15 deletions(-)
24

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

    
(3-3/4)