Browse Source

Add monitor server handling & new process handling for master

Yann Weber 4 years ago
parent
commit
7829c1c019
3 changed files with 116 additions and 16 deletions
  1. 4
    0
      include/responder.h
  2. 93
    16
      src/main.c
  3. 19
    0
      src/responder.c

+ 4
- 0
include/responder.h View File

@@ -60,6 +60,10 @@
60 60
 
61 61
 void init_context();
62 62
 
63
+/**@brief Start a new pool_handler process
64
+ * @return the new PID or -1 if error */
65
+pid_t spawn_pool_handler();
66
+
63 67
 /**@brief The responder loop
64 68
  * @ingroup work_master_proc
65 69
  * The main function of the fcgi app fork child

+ 93
- 16
src/main.c View File

@@ -37,6 +37,7 @@
37 37
 #include <string.h>
38 38
 #include <errno.h>
39 39
 #include <signal.h>
40
+#include <time.h>
40 41
 #include <sys/types.h>
41 42
 #include <sys/wait.h>
42 43
 
@@ -53,6 +54,7 @@
53 54
 extern pyfcgi_conf_t PyFCGI_conf;
54 55
 
55 56
 pid_t pool_handler_pid;
57
+pid_t monitor_serv_pid;
56 58
 
57 59
 void sighandler(int signum)
58 60
 {
@@ -78,6 +80,11 @@ void sighandler(int signum)
78 80
 		kill(pool_handler_pid, SIGTERM);
79 81
 		waitpid(pool_handler_pid, &ret, 0);
80 82
 	}
83
+	if(monitor_serv_pid)
84
+	{
85
+		kill(monitor_serv_pid, SIGTERM);
86
+		waitpid(monitor_serv_pid, &ret, 0);
87
+	}
81 88
 	pyfcgi_log(LOG_INFO,
82 89
 		"Master process exiting.");
83 90
 	exit(0);
@@ -92,9 +99,14 @@ void debug_sighandler(int signum)
92 99
 
93 100
 int main(int argc, char **argv)
94 101
 {
102
+	int emerg_sleep = 3;
95 103
 	int child_ret;
96
-	unsigned int emerg_sleep = 3;
104
+	pid_t rpid;
97 105
 	struct sigaction act;
106
+	short fails, need_wait;
107
+	//Sleeping on waitpid WNOHANG
108
+	struct timespec tsleep;
109
+	char *child_name;
98 110
 
99 111
 	act.sa_handler = sighandler;
100 112
 	sigemptyset(&act.sa_mask);
@@ -119,6 +131,7 @@ int main(int argc, char **argv)
119 131
 
120 132
 
121 133
 	pool_handler_pid = 0;
134
+	monitor_serv_pid = 0;
122 135
 	default_conf();
123 136
 	pyfcgi_name_sems(getpid()); //name semaphore using master proc PID
124 137
 
@@ -133,34 +146,98 @@ int main(int argc, char **argv)
133 146
 
134 147
 	while(1)
135 148
 	{
136
-		pool_handler_pid = fork();
137
-		if(pool_handler_pid == -1)
149
+		if(PyFCGI_conf.mon_socket && !monitor_serv_pid)
150
+		{
151
+			monitor_serv_pid = pyfcgi_spawn_monitor();
152
+			if(monitor_serv_pid < 0)
153
+			{
154
+				fails = 1;
155
+				monitor_serv_pid = 0;
156
+			}
157
+		}
158
+		if(!pool_handler_pid)
159
+		{
160
+			pool_handler_pid = spawn_pool_handler();
161
+			if(pool_handler_pid < 0)
162
+			{
163
+				fails = 1;
164
+				pool_handler_pid = 0;
165
+			}
166
+		}
167
+		if(fails)
168
+		{
169
+			if(emerg_sleep > 600)
170
+			{
171
+				pyfcgi_log(LOG_EMERG, "Abording...");
172
+				exit(PYFCGI_FATAL);
173
+			}
174
+			fails = 0;
175
+			pyfcgi_log(LOG_WARNING, "Sleeping %ds",
176
+				emerg_sleep);
177
+			emerg_sleep *= 2;
178
+			continue;
179
+		}
180
+		else
181
+		{
182
+			emerg_sleep = 3;
183
+		}
184
+
185
+		need_wait = ((!PyFCGI_conf.mon_socket || monitor_serv_pid)
186
+			&& pool_handler_pid);
187
+		rpid = waitpid(0, &child_ret, need_wait?0:WNOHANG);
188
+		if(rpid == pool_handler_pid)
189
+		{
190
+			child_name = "Pool handler";
191
+			pool_handler_pid = 0;
192
+			if(!child_ret)
193
+			{
194
+				pyfcgi_log(LOG_NOTICE,
195
+					"Restarting main process after %d requests",
196
+					MAX_REQS);
197
+				continue;
198
+			}
199
+		}
200
+		else if(rpid == monitor_serv_pid)
138 201
 		{
139
-			// TODO : Error
140
-			pyfcgi_log(LOG_EMERG, "Failed to fork : '%s' sleeping %ds", strerror(errno), emerg_sleep);
141
-			sleep(emerg_sleep);
202
+			child_name = "Monitor server";
203
+			monitor_serv_pid = 0;
204
+		}
205
+		else if(rpid == 0 && !need_wait)
206
+		{
207
+			tsleep.tv_sec = 0;
208
+			tsleep.tv_nsec = 100000000;
209
+			nanosleep(&tsleep, NULL);
142 210
 			continue;
143 211
 		}
144
-		else if(!pool_handler_pid)
212
+		else if(rpid < 0)
145 213
 		{
146
-			responder_loop();
147
-			exit((unsigned char)-1);
214
+			pyfcgi_log(LOG_EMERG, "Unable to waitpid : %s",
215
+				strerror(errno));
216
+			exit(PYFCGI_FATAL);
148 217
 		}
149
-		waitpid(pool_handler_pid, &child_ret, 0);
150
-		pool_handler_pid = 0;
218
+		else
219
+		{
220
+			child_name = "Unknown child";
221
+			pyfcgi_log(LOG_WARNING,
222
+				"Unknown child (PID %d) exited...", rpid);
223
+		}
224
+
151 225
 		if(child_ret)
152 226
 		{
153
-			pyfcgi_log(LOG_ERR, "Responder loop function exits with error code '%d'",
154
-				WEXITSTATUS(child_ret));
227
+
228
+			pyfcgi_log(LOG_ERR, "%s exits with error code '%d'",
229
+				child_name, WEXITSTATUS(child_ret));
155 230
 			if(WIFSIGNALED(child_ret))
156 231
 			{
157
-				pyfcgi_log(LOG_ERR, "Responder loop function terminated by sig '%d'",
158
-					WTERMSIG(child_ret));
232
+				pyfcgi_log(LOG_ERR, "%s terminated by sig '%d'",
233
+					child_name, WTERMSIG(child_ret));
159 234
 			}
160 235
 		}
161 236
 		else
162 237
 		{
163
-			pyfcgi_log(LOG_NOTICE, "Restarting main process after %d requests", MAX_REQS);
238
+			pyfcgi_log(LOG_WARNING,
239
+				"%s exits with no error status 0",
240
+				child_name);
164 241
 		}
165 242
 	}
166 243
 

+ 19
- 0
src/responder.c View File

@@ -29,6 +29,25 @@ static void clean_exit(int status)
29 29
 	exit(status);
30 30
 }
31 31
 
32
+pid_t spawn_pool_handler()
33
+{
34
+	pid_t res;
35
+
36
+	res = fork();
37
+	if(res < 0)
38
+	{
39
+		pyfcgi_log(LOG_ALERT, "Failed to fork pool_handler : %s",
40
+			strerror(errno));
41
+		return -1;
42
+	}
43
+	if(!res)
44
+	{
45
+		responder_loop();
46
+		exit((unsigned char)-1);
47
+	}
48
+	return res;
49
+}
50
+
32 51
 void init_context()
33 52
 {
34 53
 	PyFCGI_conf.context.pid = getpid();

Loading…
Cancel
Save