Skip to content

Commit 403a58c

Browse files
committed
add experimental dynamic process spawning support (patch by Jerome Loyet)
1 parent a766203 commit 403a58c

14 files changed

+251
-44
lines changed

sapi/fpm/fpm/fastcgi.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -986,13 +986,13 @@ int fcgi_accept_request(fcgi_request *req)
986986
int n = 0;
987987
int allowed = 0;
988988

989-
while (allowed_clients[n] != INADDR_NONE) {
990-
if (allowed_clients[n] == sa.sa_inet.sin_addr.s_addr) {
991-
allowed = 1;
992-
break;
993-
}
994-
n++;
989+
while (allowed_clients[n] != INADDR_NONE) {
990+
if (allowed_clients[n] == sa.sa_inet.sin_addr.s_addr) {
991+
allowed = 1;
992+
break;
995993
}
994+
n++;
995+
}
996996
if (!allowed) {
997997
fprintf(stderr, "Connection from disallowed IP address '%s' is dropped.\n", inet_ntoa(sa.sa_inet.sin_addr));
998998
closesocket(req->fd);

sapi/fpm/fpm/fpm_children.c

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,6 @@
3232
static time_t *last_faults;
3333
static int fault;
3434

35-
static int fpm_children_make(struct fpm_worker_pool_s *wp, int in_event_loop);
36-
3735
static void fpm_children_cleanup(int which, void *arg) /* {{{ */
3836
{
3937
free(last_faults);
@@ -180,13 +178,21 @@ void fpm_children_bury() /* {{{ */
180178
while ( (pid = waitpid(-1, &status, WNOHANG | WUNTRACED)) > 0) {
181179
char buf[128];
182180
int severity = ZLOG_NOTICE;
181+
int restart_child = 1;
183182

184183
child = fpm_child_find(pid);
185184

186185
if (WIFEXITED(status)) {
187186

188187
snprintf(buf, sizeof(buf), "with code %d", WEXITSTATUS(status));
189188

189+
/* if it's been killed because of dynamic process management
190+
* don't restart it automaticaly
191+
*/
192+
if (child && child->idle_kill) {
193+
restart_child = 0;
194+
}
195+
190196
if (WEXITSTATUS(status) != 0) {
191197
severity = ZLOG_WARNING;
192198
}
@@ -201,6 +207,13 @@ void fpm_children_bury() /* {{{ */
201207

202208
snprintf(buf, sizeof(buf), "on signal %d %s%s", WTERMSIG(status), signame, have_core);
203209

210+
/* if it's been killed because of dynamic process management
211+
* don't restart it automaticaly
212+
*/
213+
if (child && child->idle_kill && WTERMSIG(status) == SIGTERM) {
214+
restart_child = 0;
215+
}
216+
204217
if (WTERMSIG(status) != SIGQUIT) { /* possible request loss */
205218
severity = ZLOG_WARNING;
206219
}
@@ -227,8 +240,11 @@ void fpm_children_bury() /* {{{ */
227240

228241
timersub(&tv1, &child->started, &tv2);
229242

230-
zlog(ZLOG_STUFF, severity, "child %d (pool %s) exited %s after %ld.%06d seconds from start", (int) pid,
231-
child->wp->config->name, buf, tv2.tv_sec, (int) tv2.tv_usec);
243+
if (restart_child) {
244+
zlog(ZLOG_STUFF, severity, "child %d (pool %s) exited %s after %ld.%06d seconds from start", (int) pid, child->wp->config->name, buf, tv2.tv_sec, (int) tv2.tv_usec);
245+
} else {
246+
zlog(ZLOG_STUFF, severity, "child %d (pool %s) has been killed by the process managment after %ld.%06d seconds from start", (int) pid, child->wp->config->name, tv2.tv_sec, (int) tv2.tv_usec);
247+
}
232248

233249
fpm_child_close(child, 1 /* in event_loop */);
234250

@@ -254,17 +270,18 @@ void fpm_children_bury() /* {{{ */
254270

255271
if (restart_condition) {
256272

257-
zlog(ZLOG_STUFF, ZLOG_WARNING, "failed processes threshold (%d in %d sec) is reached, initiating reload",
258-
fpm_global_config.emergency_restart_threshold, fpm_global_config.emergency_restart_interval);
273+
zlog(ZLOG_STUFF, ZLOG_WARNING, "failed processes threshold (%d in %d sec) is reached, initiating reload", fpm_global_config.emergency_restart_threshold, fpm_global_config.emergency_restart_interval);
259274

260275
fpm_pctl(FPM_PCTL_STATE_RELOADING, FPM_PCTL_ACTION_SET);
261276
}
262277
}
263278

264-
fpm_children_make(wp, 1 /* in event loop */);
279+
if (restart_child) {
280+
fpm_children_make(wp, 1 /* in event loop */, 1);
265281

266-
if (fpm_globals.is_child) {
267-
break;
282+
if (fpm_globals.is_child) {
283+
break;
284+
}
268285
}
269286
} else {
270287
zlog(ZLOG_STUFF, ZLOG_ALERT, "oops, unknown child exited %s", buf);
@@ -326,14 +343,24 @@ static void fpm_parent_resources_use(struct fpm_child_s *child) /* {{{ */
326343
}
327344
/* }}} */
328345

329-
static int fpm_children_make(struct fpm_worker_pool_s *wp, int in_event_loop) /* {{{ */
346+
int fpm_children_make(struct fpm_worker_pool_s *wp, int in_event_loop, int nb_to_spawn) /* {{{ */
330347
{
331348
int enough = 0;
332349
pid_t pid;
333350
struct fpm_child_s *child;
351+
int max;
334352

335-
while (!enough && fpm_pctl_can_spawn_children() && wp->running_children < wp->config->pm->max_children) {
353+
if (wp->config->pm->style == PM_STYLE_DYNAMIC) {
354+
if (!in_event_loop) { /* stating */
355+
max = wp->config->pm->dynamic.start_servers;
356+
} else {
357+
max = wp->running_children + nb_to_spawn;
358+
}
359+
} else { /* PM_STYLE_STATIC */
360+
max = wp->config->pm->max_children;
361+
}
336362

363+
while (!enough && fpm_pctl_can_spawn_children() && wp->running_children < max) {
337364
child = fpm_resources_prepare(wp);
338365

339366
if (!child) {
@@ -378,7 +405,7 @@ static int fpm_children_make(struct fpm_worker_pool_s *wp, int in_event_loop) /*
378405

379406
int fpm_children_create_initial(struct fpm_worker_pool_s *wp) /* {{{ */
380407
{
381-
return fpm_children_make(wp, 0 /* not in event loop yet */);
408+
return fpm_children_make(wp, 0 /* not in event loop yet */, 0);
382409
}
383410
/* }}} */
384411

sapi/fpm/fpm/fpm_children.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ int fpm_children_create_initial(struct fpm_worker_pool_s *wp);
1515
int fpm_children_free(struct fpm_child_s *child);
1616
void fpm_children_bury();
1717
int fpm_children_init_main();
18+
int fpm_children_make(struct fpm_worker_pool_s *wp, int in_event_loop, int nb_to_spawn);
1819

1920
struct fpm_child_s;
2021

@@ -27,6 +28,7 @@ struct fpm_child_s {
2728
int fd_stdout, fd_stderr;
2829
void (*tracer)(struct fpm_child_s *);
2930
struct timeval slow_logged;
31+
int idle_kill;
3032
pid_t pid;
3133
};
3234

sapi/fpm/fpm/fpm_conf.c

Lines changed: 50 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,8 @@ static char *fpm_conf_set_pm_style(void **conf, char *name, void *vv, intptr_t o
8282

8383
if (!strcmp(value, "static")) {
8484
c->style = PM_STYLE_STATIC;
85-
} else if (!strcmp(value, "apache-like")) {
86-
c->style = PM_STYLE_APACHE_LIKE;
85+
} else if (!strcmp(value, "dynamic")) {
86+
c->style = PM_STYLE_DYNAMIC;
8787
} else {
8888
return "invalid value for 'style'";
8989
}
@@ -139,19 +139,19 @@ static char *fpm_conf_set_catch_workers_output(void **conf, char *name, void *vv
139139
}
140140
/* }}} */
141141

142-
static struct xml_conf_section fpm_conf_set_apache_like_subsection_conf = {
143-
.path = "apache_like somewhere", /* fixme */
142+
static struct xml_conf_section fpm_conf_set_dynamic_subsection_conf = {
143+
.path = "dynamic somewhere", /* fixme */
144144
.parsers = (struct xml_value_parser []) {
145-
{ XML_CONF_SCALAR, "StartServers", &xml_conf_set_slot_integer, offsetof(struct fpm_pm_s, options_apache_like.StartServers) },
146-
{ XML_CONF_SCALAR, "MinSpareServers", &xml_conf_set_slot_integer, offsetof(struct fpm_pm_s, options_apache_like.MinSpareServers) },
147-
{ XML_CONF_SCALAR, "MaxSpareServers", &xml_conf_set_slot_integer, offsetof(struct fpm_pm_s, options_apache_like.MaxSpareServers) },
145+
{ XML_CONF_SCALAR, "start_servers", &xml_conf_set_slot_integer, offsetof(struct fpm_pm_s, dynamic.start_servers) },
146+
{ XML_CONF_SCALAR, "min_spare_servers", &xml_conf_set_slot_integer, offsetof(struct fpm_pm_s, dynamic.min_spare_servers) },
147+
{ XML_CONF_SCALAR, "max_spare_servers", &xml_conf_set_slot_integer, offsetof(struct fpm_pm_s, dynamic.max_spare_servers) },
148148
{ 0, 0, 0, 0 }
149149
}
150150
};
151151

152-
static char *fpm_conf_set_apache_like_subsection(void **conf, char *name, void *xml_node, intptr_t offset) /* {{{ */
152+
static char *fpm_conf_set_dynamic_subsection(void **conf, char *name, void *xml_node, intptr_t offset) /* {{{ */
153153
{
154-
return xml_conf_parse_section(conf, &fpm_conf_set_apache_like_subsection_conf, xml_node);
154+
return xml_conf_parse_section(conf, &fpm_conf_set_dynamic_subsection_conf, xml_node);
155155
}
156156
/* }}} */
157157

@@ -191,7 +191,7 @@ static struct xml_conf_section fpm_conf_set_pm_subsection_conf = {
191191
.parsers = (struct xml_value_parser []) {
192192
{ XML_CONF_SCALAR, "style", &fpm_conf_set_pm_style, 0 },
193193
{ XML_CONF_SCALAR, "max_children", &xml_conf_set_slot_integer, offsetof(struct fpm_pm_s, max_children) },
194-
{ XML_CONF_SUBSECTION, "apache_like", &fpm_conf_set_apache_like_subsection, offsetof(struct fpm_pm_s, options_apache_like) },
194+
{ XML_CONF_SUBSECTION, "dynamic", &fpm_conf_set_dynamic_subsection, offsetof(struct fpm_pm_s, dynamic) },
195195
{ 0, 0, 0, 0 }
196196
}
197197
};
@@ -392,6 +392,46 @@ static int fpm_conf_process_all_pools() /* {{{ */
392392
wp->is_template = 1;
393393
}
394394

395+
if (wp->config->pm == NULL) {
396+
zlog(ZLOG_STUFF, ZLOG_ALERT, "pool %s: the process manager is missing (static or dynamic)", wp->config->name);
397+
return(-1);
398+
}
399+
400+
if (wp->config->pm->style == PM_STYLE_DYNAMIC) {
401+
struct fpm_pm_s *pm = wp->config->pm;
402+
403+
if (pm->dynamic.min_spare_servers <= 0) {
404+
zlog(ZLOG_STUFF, ZLOG_ALERT, "pool %s: min_spare_servers must be a positive value", wp->config->name);
405+
return(-1);
406+
}
407+
408+
if (pm->dynamic.max_spare_servers <= 0) {
409+
zlog(ZLOG_STUFF, ZLOG_ALERT, "pool %s: max_spare_servers must be a positive value", wp->config->name);
410+
return(-1);
411+
}
412+
413+
if (pm->dynamic.min_spare_servers > pm->max_children ||
414+
pm->dynamic.max_spare_servers > pm->max_children) {
415+
zlog(ZLOG_STUFF, ZLOG_ALERT, "pool %s: min_spare_servers(%d) and max_spare_servers(%d) can't be greater than max_children(%d)",
416+
wp->config->name, pm->dynamic.min_spare_servers, pm->dynamic.max_spare_servers, pm->max_children);
417+
return(-1);
418+
}
419+
420+
if (pm->dynamic.max_spare_servers < pm->dynamic.min_spare_servers) {
421+
zlog(ZLOG_STUFF, ZLOG_ALERT, "pool %s: max_spare_servers must be greater or equal than min_spare_servers", wp->config->name);
422+
return(-1);
423+
}
424+
425+
if (pm->dynamic.start_servers <= 0) {
426+
pm->dynamic.start_servers = pm->dynamic.min_spare_servers + ((pm->dynamic.max_spare_servers - pm->dynamic.min_spare_servers) / 2);
427+
zlog(ZLOG_STUFF, ZLOG_NOTICE, "pool %s: start_servers has been set to %d", wp->config->name, pm->dynamic.start_servers);
428+
} else if (pm->dynamic.start_servers < pm->dynamic.min_spare_servers || pm->dynamic.start_servers > pm->dynamic.max_spare_servers) {
429+
zlog(ZLOG_STUFF, ZLOG_ALERT, "pool %s: start_servers must not be less than min_spare_servers and not greaters than max_spare_servers", wp->config->name);
430+
return(-1);
431+
}
432+
}
433+
434+
395435
if (wp->config->request_slowlog_timeout) {
396436
#if HAVE_FPM_TRACE
397437
if (! (wp->config->slowlog && *wp->config->slowlog)) {

sapi/fpm/fpm/fpm_conf.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@ struct fpm_pm_s {
2828
int style;
2929
int max_children;
3030
struct {
31-
int StartServers;
32-
int MinSpareServers;
33-
int MaxSpareServers;
34-
} options_apache_like;
31+
int start_servers;
32+
int min_spare_servers;
33+
int max_spare_servers;
34+
} dynamic;
3535
};
3636

3737
struct fpm_listen_options_s {
@@ -62,7 +62,7 @@ struct fpm_worker_pool_config_s {
6262
unsigned catch_workers_output:1;
6363
};
6464

65-
enum { PM_STYLE_STATIC = 1, PM_STYLE_APACHE_LIKE = 2 };
65+
enum { PM_STYLE_STATIC = 1, PM_STYLE_DYNAMIC = 2 };
6666

6767
int fpm_conf_init_main();
6868
int fpm_worker_pool_config_free(struct fpm_worker_pool_config_s *wpc);

sapi/fpm/fpm/fpm_config.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@
3232
} while (0)
3333
#endif
3434

35+
#ifndef MIN
36+
#define MIN(a,b) (((a)<(b))?(a):(b))
37+
#endif
38+
3539
#if defined(HAVE_PTRACE) || defined(PROC_MEM_FILE) || defined(HAVE_MACH_VM_READ)
3640
#define HAVE_FPM_TRACE 1
3741
#else

sapi/fpm/fpm/fpm_events.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ int fpm_event_loop() /* {{{ */
100100
event_set(&signal_fd_event, fpm_signals_get_fd(), EV_PERSIST | EV_READ, &fpm_got_signal, 0);
101101
event_add(&signal_fd_event, 0);
102102
fpm_pctl_heartbeat(-1, 0, 0);
103+
fpm_pctl_perform_idle_server_maintenance_heartbeat(-1, 0, 0);
103104
zlog(ZLOG_STUFF, ZLOG_NOTICE, "libevent: entering main loop");
104105
event_loop(0);
105106
return 0;

0 commit comments

Comments
 (0)