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
 
60
 
61
 void init_context();
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
 /**@brief The responder loop
67
 /**@brief The responder loop
64
  * @ingroup work_master_proc
68
  * @ingroup work_master_proc
65
  * The main function of the fcgi app fork child
69
  * The main function of the fcgi app fork child

+ 93
- 16
src/main.c View File

37
 #include <string.h>
37
 #include <string.h>
38
 #include <errno.h>
38
 #include <errno.h>
39
 #include <signal.h>
39
 #include <signal.h>
40
+#include <time.h>
40
 #include <sys/types.h>
41
 #include <sys/types.h>
41
 #include <sys/wait.h>
42
 #include <sys/wait.h>
42
 
43
 
53
 extern pyfcgi_conf_t PyFCGI_conf;
54
 extern pyfcgi_conf_t PyFCGI_conf;
54
 
55
 
55
 pid_t pool_handler_pid;
56
 pid_t pool_handler_pid;
57
+pid_t monitor_serv_pid;
56
 
58
 
57
 void sighandler(int signum)
59
 void sighandler(int signum)
58
 {
60
 {
78
 		kill(pool_handler_pid, SIGTERM);
80
 		kill(pool_handler_pid, SIGTERM);
79
 		waitpid(pool_handler_pid, &ret, 0);
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
 	pyfcgi_log(LOG_INFO,
88
 	pyfcgi_log(LOG_INFO,
82
 		"Master process exiting.");
89
 		"Master process exiting.");
83
 	exit(0);
90
 	exit(0);
92
 
99
 
93
 int main(int argc, char **argv)
100
 int main(int argc, char **argv)
94
 {
101
 {
102
+	int emerg_sleep = 3;
95
 	int child_ret;
103
 	int child_ret;
96
-	unsigned int emerg_sleep = 3;
104
+	pid_t rpid;
97
 	struct sigaction act;
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
 	act.sa_handler = sighandler;
111
 	act.sa_handler = sighandler;
100
 	sigemptyset(&act.sa_mask);
112
 	sigemptyset(&act.sa_mask);
119
 
131
 
120
 
132
 
121
 	pool_handler_pid = 0;
133
 	pool_handler_pid = 0;
134
+	monitor_serv_pid = 0;
122
 	default_conf();
135
 	default_conf();
123
 	pyfcgi_name_sems(getpid()); //name semaphore using master proc PID
136
 	pyfcgi_name_sems(getpid()); //name semaphore using master proc PID
124
 
137
 
133
 
146
 
134
 	while(1)
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
 			continue;
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
 		if(child_ret)
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
 			if(WIFSIGNALED(child_ret))
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
 		else
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
 	exit(status);
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
 void init_context()
51
 void init_context()
33
 {
52
 {
34
 	PyFCGI_conf.context.pid = getpid();
53
 	PyFCGI_conf.context.pid = getpid();

Loading…
Cancel
Save