php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Return to Bug #52569
Patch fpm-ondemand.v11-5.3.patch revision 2011-07-14 22:38 UTC by fat@php.net
Patch fpm-ondemand.v11.patch revision 2011-07-14 22:27 UTC by fat@php.net
Patch fpm-ondemand.v10-5.3.patch revision 2011-07-10 17:49 UTC by fat@php.net
Patch fpm-ondemand.v10.patch revision 2011-07-10 17:49 UTC by fat@php.net
Patch fpm-ondemand.v9-5.3.patch revision 2011-07-09 12:30 UTC by fat@php.net
Patch fpm-ondemand.v9.patch revision 2011-07-09 12:30 UTC by fat@php.net
Patch fpm-ondemand.v8-5.3.patch revision 2011-07-09 00:22 UTC by fat@php.net
Patch fpm-ondemand.v8.patch revision 2011-07-09 00:21 UTC by fat@php.net
Patch fpm-ondemand.v7-5.3.patch revision 2011-07-05 23:12 UTC by fat@php.net
Patch fpm-ondemand.v7.patch revision 2011-07-05 23:08 UTC by fat@php.net
Patch fpm-ondemand-pm-v6 revision 2010-09-25 16:27 UTC by mplomer at gmx dot de
Patch php-fpm-ondemand-pm-v5 revision 2010-08-30 08:16 UTC by mplomer at gmx dot de
Patch fpm-ondemand.v4.patch revision 2010-08-27 06:27 UTC by fat@php.net
Patch fpm-ondemand-pm-v3 revision 2010-08-25 22:12 UTC by mplomer at gmx dot de
Patch fpm-ondemand.v2.patch.txt revision 2010-08-23 22:51 UTC by fat@php.net
Patch fpm-ondemand-pm-php53 revision 2010-08-10 18:01 UTC by mplomer at gmx dot de
Patch fpm-ondemand-pm revision 2010-08-09 20:14 UTC by fat@php.net

Patch fpm-ondemand-pm-php53 for FPM related Bug #52569

Patch version 2010-08-10 18:01 UTC

Return to Bug #52569 | Download this patch
This patch is obsolete

Obsoleted by patches:

This patch renders other patches obsolete

Obsolete patches:

Patch Revisions:

Developer: mplomer@gmx.de

Index: fpm_children.c
===================================================================
--- fpm_children.c	(revision 302051)
+++ fpm_children.c	(working copy)
@@ -361,6 +361,12 @@
 		} else {
 			max = wp->running_children + nb_to_spawn;
 		}
+	} else if (wp->config->pm == PM_STYLE_ONDEMAND) {
+		if (!in_event_loop) { /* starting */
+			max = 0;
+		} else {
+			max = wp->running_children + nb_to_spawn;
+		}
 	} else { /* PM_STYLE_STATIC */
 		max = wp->config->pm_max_children;
 	}
@@ -411,6 +417,20 @@
 
 int fpm_children_create_initial(struct fpm_worker_pool_s *wp, struct event_base *base) /* {{{ */
 {
+	if (wp->config->pm == PM_STYLE_ONDEMAND) {
+		wp->socket_event = (struct event *)malloc(sizeof(struct event));
+		if (!wp->socket_event) {
+			zlog(ZLOG_STUFF, ZLOG_ERROR, "[pool %s] unable to malloc the socket event", wp->config->name);
+			return 1;
+		}
+		wp->base = base;
+		wp->last_fork.tv_sec = 0;
+		wp->last_fork.tv_usec = 0;
+		event_set(wp->socket_event, wp->listening_socket, EV_PERSIST | EV_READ, fpm_pctl_on_socket_accept, wp);
+		event_base_set(base, wp->socket_event);
+		event_add(wp->socket_event, 0);
+		return 1;
+	}
 	return fpm_children_make(wp, 0 /* not in event loop yet */, 0, 1, base);
 }
 /* }}} */
Index: fpm_conf.c
===================================================================
--- fpm_conf.c	(revision 302051)
+++ fpm_conf.c	(working copy)
@@ -259,6 +259,8 @@
 		c->pm = PM_STYLE_STATIC;
 	} else if (!strcasecmp(val, "dynamic")) {
 		c->pm = PM_STYLE_DYNAMIC;
+	} else if (!strcasecmp(val, "ondemand")) {
+		c->pm = PM_STYLE_ONDEMAND;
 	} else {
 		return "invalid process manager (static or dynamic)";
 	}
@@ -430,8 +432,8 @@
 			return -1;
 		}
 
-		if (wp->config->pm != PM_STYLE_STATIC && wp->config->pm != PM_STYLE_DYNAMIC) {
-			zlog(ZLOG_STUFF, ZLOG_ALERT, "[pool %s] the process manager is missing (static or dynamic)", wp->config->name);
+		if (wp->config->pm != PM_STYLE_STATIC && wp->config->pm != PM_STYLE_DYNAMIC && wp->config->pm != PM_STYLE_ONDEMAND) {
+			zlog(ZLOG_STUFF, ZLOG_ALERT, "[pool %s] the process manager is missing (static, dynamic or ondemand)", wp->config->name);
 			return -1;
 		}
 
@@ -472,7 +474,10 @@
 				zlog(ZLOG_STUFF, ZLOG_ALERT, "[pool %s] pm.start_servers(%d) must not be less than pm.min_spare_servers(%d) and not greater than pm.max_spare_servers(%d)", wp->config->name, config->pm_start_servers, config->pm_min_spare_servers, config->pm_max_spare_servers);
 				return -1;
 			}
-
+		} else {
+			wp->config->pm_start_servers = 0;
+			wp->config->pm_min_spare_servers = 0;
+			wp->config->pm_max_spare_servers = 0;
 		}
 
 
Index: fpm_conf.h
===================================================================
--- fpm_conf.h	(revision 302051)
+++ fpm_conf.h	(working copy)
@@ -67,7 +67,7 @@
 	intptr_t offset;
 };
 
-enum { PM_STYLE_STATIC = 1, PM_STYLE_DYNAMIC = 2 };
+enum { PM_STYLE_STATIC = 1, PM_STYLE_DYNAMIC = 2, PM_STYLE_ONDEMAND = 3 };
 
 int fpm_conf_init_main();
 int fpm_worker_pool_config_free(struct fpm_worker_pool_config_s *wpc);
Index: fpm_process_ctl.c
===================================================================
--- fpm_process_ctl.c	(revision 302051)
+++ fpm_process_ctl.c	(working copy)
@@ -351,6 +351,23 @@
 		/* update status structure for all PMs */
 		fpm_status_update_activity(wp->shm_status, idle, active, idle + active, 0);
 
+		/* this is specific to PM_STYLE_ONDEMAND */
+		if (wp->config->pm == PM_STYLE_ONDEMAND) {
+			struct timeval last, now;
+
+			zlog(ZLOG_STUFF, ZLOG_DEBUG, "[pool %s] currently %d active children, %d spare children", wp->config->name, active, idle);
+
+			if (!last_idle_child) continue;
+
+			fpm_request_last_activity(last_idle_child, &last);
+			fpm_clock_get(&now);
+			if (last.tv_sec < now.tv_sec - 10) {
+				last_idle_child->idle_kill = 1;
+				fpm_pctl_kill(last_idle_child->pid, FPM_PCTL_TERM);
+			}
+			continue;
+		}
+
 		/* the rest is only used by PM_STYLE_DYNAMIC */
 		if (wp->config->pm != PM_STYLE_DYNAMIC) continue;
 
@@ -461,3 +478,35 @@
 }
 /* }}} */
 
+void fpm_pctl_on_socket_accept(int fd, short which, void *arg) /* {{{ */
+{
+	struct fpm_worker_pool_s *wp = (struct fpm_worker_pool_s *)arg;
+	struct fpm_child_s *child;
+	struct timeval now, diff;
+
+
+	if (fpm_globals.parent_pid != getpid()) {
+		/* prevent a event race condition when child process
+		* have not set up its own event loop */
+		return;
+	}
+
+
+	fpm_clock_get(&now);
+	timersub(&now, &wp->last_fork, &diff);
+	// if we forked in the last 500us, do nothing
+	if (diff.tv_sec == 0 && diff.tv_usec < 500) return;
+	wp->last_fork.tv_sec = 0;
+	wp->last_fork.tv_usec = 0;
+
+	for (child = wp->children; child; child = child->next) {
+		/* if there is at least on idle child, it will handle the connection, stop here */
+		if (fpm_request_is_idle(child)) {
+			return;
+		}
+	}
+	fpm_clock_get(&wp->last_fork);
+	fpm_children_make(wp, 1, 1, 1, wp->base);
+	zlog(ZLOG_STUFF, ZLOG_DEBUG, "[pool %s] got accept without idle child available .... I forked, now=%d.%d", wp->config->name, now.tv_sec, now.tv_usec);
+}
+/* }}} */
Index: fpm_process_ctl.h
===================================================================
--- fpm_process_ctl.h	(revision 302051)
+++ fpm_process_ctl.h	(working copy)
@@ -17,6 +17,7 @@
 int fpm_pctl_kill(pid_t pid, int how);
 void fpm_pctl_heartbeat(int fd, short which, void *arg);
 void fpm_pctl_perform_idle_server_maintenance_heartbeat(int fd, short which, void *arg);
+void fpm_pctl_on_socket_accept(int fd, short which, void *arg);
 int fpm_pctl_child_exited();
 int fpm_pctl_init_main();
 
Index: fpm_request.c
===================================================================
--- fpm_request.c	(revision 302051)
+++ fpm_request.c	(working copy)
@@ -167,3 +167,22 @@
 	return(!slot_c.accepted.tv_sec && !slot_c.accepted.tv_usec ? 1 : 0);
 }
 /* }}} */
+
+int fpm_request_last_activity(struct fpm_child_s *child, struct timeval *tv) /* {{{ */
+{
+	struct fpm_shm_slot_s *slot;
+	struct fpm_shm_slot_s slot_c;
+
+	if (!tv) return -1;
+
+	slot = fpm_shm_slot(child);
+	if (!fpm_shm_slots_acquire(slot, 1)) {
+		return -1;
+	}
+
+	slot_c = *slot;
+	fpm_shm_slots_release(slot);
+	*tv = slot_c.tv;
+	return 1;
+}
+/* }}} */
Index: fpm_request.h
===================================================================
--- fpm_request.h	(revision 302051)
+++ fpm_request.h	(working copy)
@@ -16,6 +16,7 @@
 
 void fpm_request_check_timed_out(struct fpm_child_s *child, struct timeval *tv, int terminate_timeout, int slowlog_timeout);
 int fpm_request_is_idle(struct fpm_child_s *child);
+int fpm_request_last_activity(struct fpm_child_s *child, struct timeval *tv);
 
 enum fpm_request_stage_e {
 	FPM_REQUEST_ACCEPTING = 1,
Index: fpm_worker_pool.h
===================================================================
--- fpm_worker_pool.h	(revision 302051)
+++ fpm_worker_pool.h	(working copy)
@@ -38,6 +38,9 @@
 	int idle_spawn_rate;
 	int warn_max_children;
 	struct fpm_shm_s *shm_status;
+	struct event *socket_event;
+	struct event_base *base;
+	struct timeval last_fork;
 };
 
 struct fpm_worker_pool_s *fpm_worker_pool_alloc();
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Tue Mar 19 03:01:29 2024 UTC