|
@@ -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
|
|