From 5d517e16f04fff601e1e44085c9bdecc5d09ec14 Mon Sep 17 00:00:00 2001 From: Masahiro Nagano Date: Fri, 6 Jan 2017 09:36:30 +0900 Subject: [PATCH 1/6] Add decide_action callback --- lib/Prefork.php | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/lib/Prefork.php b/lib/Prefork.php index 3f99fcf..5f76711 100644 --- a/lib/Prefork.php +++ b/lib/Prefork.php @@ -30,6 +30,10 @@ class Prefork * @var callable lamda function that is called when a child is reaped */ public $on_child_reap = null; + /** + * @var callable lamda fuction that decide action + */ + public $decide_action = null; private $signal_received = null; private $manager_pid = null; @@ -43,6 +47,8 @@ function __construct(array $args = array()) ? $args['max_workers'] : $this->max_workers; $this->trap_signals = isset($args['trap_signals']) ? $args['trap_signals'] : $this->trap_signals; + $this->decide_action = isset($args['decide_action']) + ? $args['decide_action'] : null; foreach (array_keys($this->trap_signals) as $sig) { pcntl_signal($sig, array($this, '_signalHandler'), false); @@ -75,7 +81,13 @@ public function start() // main loop while ($this->signal_received === null) { $pid = null; - if (count(array_keys($this->worker_pids)) < $this->max_workers) { + $action = count(array_keys($obj->worker_pids)) < $obj->max_workers; + try { + $action = call_user_func_array($this->decide_action,array($this)); + } catch ( \Exception $e ) { + printf("Exception. Use default action: %s\n",$e->getMessage()); + } + if ($action) { $pid = pcntl_fork(); if ($pid === -1) { echo "fork failed!\n"; @@ -164,16 +176,16 @@ private function generation() return $this->generation; } - // PHP 5.2.x don't have lamda function private function _runChildReapCb($exit_pid, $status) { $cb = $this->on_child_reap; if ($cb) { -/* try { - $cb->($exit_pid, $status); - } -*/ + call_user_func_array($cb, array($exit_pid, $status)); + } catch (\Exception $e) { + // ignore + printf("Ignore Exception: %s\n",$e->getMessage()); + }; } } } From ae48f76fac2a055358d2d83423a2877c0fc82b11 Mon Sep 17 00:00:00 2001 From: Masahiro Nagano Date: Fri, 6 Jan 2017 09:49:12 +0900 Subject: [PATCH 2/6] pass current_workers & max_workers --- lib/Prefork.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/Prefork.php b/lib/Prefork.php index 5f76711..a1d3e2d 100644 --- a/lib/Prefork.php +++ b/lib/Prefork.php @@ -81,9 +81,10 @@ public function start() // main loop while ($this->signal_received === null) { $pid = null; - $action = count(array_keys($obj->worker_pids)) < $obj->max_workers; + $currect_workers = count(array_keys($obj->worker_pids)) + $action = $currect_workers < $this->max_workers; try { - $action = call_user_func_array($this->decide_action,array($this)); + $action = call_user_func_array($this->decide_action,array($currect_workers, $this->max_workers)); } catch ( \Exception $e ) { printf("Exception. Use default action: %s\n",$e->getMessage()); } From 61ed5456e288c2f565d570e8dfd45a006415ca37 Mon Sep 17 00:00:00 2001 From: Masahiro Nagano Date: Fri, 6 Jan 2017 09:49:48 +0900 Subject: [PATCH 3/6] fix --- lib/Prefork.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Prefork.php b/lib/Prefork.php index a1d3e2d..4b3711d 100644 --- a/lib/Prefork.php +++ b/lib/Prefork.php @@ -81,7 +81,7 @@ public function start() // main loop while ($this->signal_received === null) { $pid = null; - $currect_workers = count(array_keys($obj->worker_pids)) + $currect_workers = count(array_keys($obj->worker_pids)); $action = $currect_workers < $this->max_workers; try { $action = call_user_func_array($this->decide_action,array($currect_workers, $this->max_workers)); From 2b609619187a1695a2b86acc6e849b09fdaee44a Mon Sep 17 00:00:00 2001 From: Masahiro Nagano Date: Fri, 6 Jan 2017 09:54:49 +0900 Subject: [PATCH 4/6] fix --- lib/Prefork.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/Prefork.php b/lib/Prefork.php index 4b3711d..c46c483 100644 --- a/lib/Prefork.php +++ b/lib/Prefork.php @@ -81,12 +81,14 @@ public function start() // main loop while ($this->signal_received === null) { $pid = null; - $currect_workers = count(array_keys($obj->worker_pids)); + $currect_workers = count(array_keys($this->worker_pids)); $action = $currect_workers < $this->max_workers; - try { - $action = call_user_func_array($this->decide_action,array($currect_workers, $this->max_workers)); - } catch ( \Exception $e ) { - printf("Exception. Use default action: %s\n",$e->getMessage()); + if ( isset($this->decide_action) ) { + try { + $action = call_user_func_array($this->decide_action,array($currect_workers, $this->max_workers)); + } catch ( \Exception $e ) { + printf("Exception. Use default action: %s\n",$e->getMessage()); + } } if ($action) { $pid = pcntl_fork(); From 85a0b26940cd02cab15007fcbbcdb7d9c79d8981 Mon Sep 17 00:00:00 2001 From: Masahiro Nagano Date: Fri, 6 Jan 2017 10:13:46 +0900 Subject: [PATCH 5/6] add example --- examples/02-decide-action.php | 55 +++++++++++++++++++++++++++++++++++ lib/Prefork.php | 2 -- 2 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 examples/02-decide-action.php diff --git a/examples/02-decide-action.php b/examples/02-decide-action.php new file mode 100644 index 0000000..6b6e4c6 --- /dev/null +++ b/examples/02-decide-action.php @@ -0,0 +1,55 @@ + 5, + 'trap_signals' => array( + SIGHUP => SIGTERM, + SIGTERM => SIGTERM, + ), + )); + $start_time = time(); + $prev_workers = 5; + $pp->decide_action = function($current_worker, $max_worker) use($start_time, &$prev_workers) { + $current_time = time(); + $max_worker = $max_worker + (int)(($current_time - $start_time) / 6); + if ( $max_worker > 10 ) { + $max_worker = 10; + } + if ( $max_worker !== $prev_workers ) { + echo "===> max worker: $prev_workers => $max_worker\n"; + $prev_workers = $max_worker; + } + return $current_worker < $max_worker; + }; + while ($pp->signalReceived() !== SIGTERM) { + loadConfig(); + if ($pp->start()) { + continue; + } + workChildren(); + $pp->finish(); + } + $pp->waitAllChildren(); +} + +function loadConfig() +{ + echo "Load configuration\n"; +} + +function workChildren() +{ + for ($i = 1; $i <= 3; $i++) { + echo "Sleep $i seconds\n"; + sleep($i); + } +} diff --git a/lib/Prefork.php b/lib/Prefork.php index c46c483..cf096e9 100644 --- a/lib/Prefork.php +++ b/lib/Prefork.php @@ -47,8 +47,6 @@ function __construct(array $args = array()) ? $args['max_workers'] : $this->max_workers; $this->trap_signals = isset($args['trap_signals']) ? $args['trap_signals'] : $this->trap_signals; - $this->decide_action = isset($args['decide_action']) - ? $args['decide_action'] : null; foreach (array_keys($this->trap_signals) as $sig) { pcntl_signal($sig, array($this, '_signalHandler'), false); From 7b94aeeb40c7e7c3e0385024061f2239d05b3e5e Mon Sep 17 00:00:00 2001 From: Masahiro Nagano Date: Thu, 12 Jan 2017 17:21:17 +0900 Subject: [PATCH 6/6] fixed ambiguous variables. add varidation of decide_action --- examples/02-decide-action.php | 28 ++++++++++++++-------------- lib/Prefork.php | 22 ++++++++++++++-------- 2 files changed, 28 insertions(+), 22 deletions(-) diff --git a/examples/02-decide-action.php b/examples/02-decide-action.php index 6b6e4c6..cd32b45 100644 --- a/examples/02-decide-action.php +++ b/examples/02-decide-action.php @@ -9,27 +9,27 @@ function main() { + $start_time = time(); + $prev_workers = 5; $pp = new Prefork(array( 'max_workers' => 5, 'trap_signals' => array( SIGHUP => SIGTERM, SIGTERM => SIGTERM, ), + 'decide_action' => function($current_worker, $max_worker) use($start_time, &$prev_workers) { + $current_time = time(); + $max_worker = $max_worker + (int)(($current_time - $start_time) / 6); + if ( $max_worker > 10 ) { + $max_worker = 10; + } + if ( $max_worker !== $prev_workers ) { + echo "===> max worker: $prev_workers => $max_worker\n"; + $prev_workers = $max_worker; + } + return $current_worker < $max_worker; + }, )); - $start_time = time(); - $prev_workers = 5; - $pp->decide_action = function($current_worker, $max_worker) use($start_time, &$prev_workers) { - $current_time = time(); - $max_worker = $max_worker + (int)(($current_time - $start_time) / 6); - if ( $max_worker > 10 ) { - $max_worker = 10; - } - if ( $max_worker !== $prev_workers ) { - echo "===> max worker: $prev_workers => $max_worker\n"; - $prev_workers = $max_worker; - } - return $current_worker < $max_worker; - }; while ($pp->signalReceived() !== SIGTERM) { loadConfig(); if ($pp->start()) { diff --git a/lib/Prefork.php b/lib/Prefork.php index cf096e9..2b61ddd 100644 --- a/lib/Prefork.php +++ b/lib/Prefork.php @@ -27,13 +27,14 @@ class Prefork public $err_respawn_interval = 1; /** - * @var callable lamda function that is called when a child is reaped + * @var callable lambda function that is called when a child is reaped */ public $on_child_reap = null; + /** - * @var callable lamda fuction that decide action + * callable lambda fuction that decide action */ - public $decide_action = null; + private $decide_action = null; private $signal_received = null; private $manager_pid = null; @@ -47,6 +48,11 @@ function __construct(array $args = array()) ? $args['max_workers'] : $this->max_workers; $this->trap_signals = isset($args['trap_signals']) ? $args['trap_signals'] : $this->trap_signals; + $this->decide_action = isset($args['decide_action']) + ? $args['decide_action'] : null; + if ( isset($this->decide_action) && !is_callable($this->decide_action) ){ + die("decide_action should be callable\n"); + } foreach (array_keys($this->trap_signals) as $sig) { pcntl_signal($sig, array($this, '_signalHandler'), false); @@ -80,15 +86,15 @@ public function start() while ($this->signal_received === null) { $pid = null; $currect_workers = count(array_keys($this->worker_pids)); - $action = $currect_workers < $this->max_workers; - if ( isset($this->decide_action) ) { + $should_fork = $currect_workers < $this->max_workers; + if ( is_callable($this->decide_action) ) { try { - $action = call_user_func_array($this->decide_action,array($currect_workers, $this->max_workers)); + $should_fork = call_user_func_array($this->decide_action,array($currect_workers, $this->max_workers)); } catch ( \Exception $e ) { printf("Exception. Use default action: %s\n",$e->getMessage()); } } - if ($action) { + if ($should_fork) { $pid = pcntl_fork(); if ($pid === -1) { echo "fork failed!\n"; @@ -180,7 +186,7 @@ private function generation() private function _runChildReapCb($exit_pid, $status) { $cb = $this->on_child_reap; - if ($cb) { + if (is_callable($cb)) { try { call_user_func_array($cb, array($exit_pid, $status)); } catch (\Exception $e) {