-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathPowerSpawn.class.php
More file actions
180 lines (153 loc) · 3.71 KB
/
PowerSpawn.class.php
File metadata and controls
180 lines (153 loc) · 3.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
<?php
/*
* PowerSpawn
*
* Object wrapper for handling process forking within PHP
* Depends on PCNTL package
* Depends on POSIX package
*
* Author: Don Bauer
* E-Mail: lordgnu@me.com
*
* Date: 2011-11-04
*/
declare(ticks = 1);
class PowerSpawn {
private $myChildren;
private $parentPID;
private $shutdownCallback = null;
private $killCallback = null;
public $maxChildren = 10; // Max number of children allowed to Spawn
public $timeLimit = 0; // Time limit in seconds (0 to disable)
public $sleepCount = 100; // Number of uSeconds to sleep on Tick()
public $childData; // Variable for storage of data to be passed to the next spawned child
public $complete;
public function __construct() {
if (function_exists('pcntl_fork') && function_exists('posix_getpid')) {
// Everything is good
$this->parentPID = $this->myPID();
$this->myChildren = array();
$this->complete = false;
// Install the signal handler
pcntl_signal(SIGCHLD, array($this, 'sigHandler'));
} else {
die("You must have POSIX and PCNTL functions to use PowerSpawn\n");
}
}
public function __destruct() {
}
public function sigHandler($signo) {
switch ($signo) {
case SIGCHLD:
$this->checkChildren();
break;
}
}
public function getChildStatus($name = false) {
if ($name === false) return false;
if (isset($this->myChildren[$name])) {
return $this->myChildren[$name];
} else {
return false;
}
}
public function checkChildren() {
foreach ($this->myChildren as $i => $child) {
// Check for time running and if still running
if ($this->pidDead($child['pid']) != 0) {
// Child is dead
unset($this->myChildren[$i]);
} elseif ($this->timeLimit > 0) {
// Check the time limit
if (time() - $child['time'] >= $this->timeLimit) {
// Child had exceeded time limit
$this->killChild($child['pid']);
unset($this->myChildren[$i]);
}
}
}
}
public function myPID() {
return posix_getpid();
}
public function myParent() {
return posix_getppid();
}
public function spawnChild($name = false) {
$time = time();
$pid = pcntl_fork();
if ($pid) {
if ($name !== false) {
$this->myChildren[$name] = array('time'=>$time,'pid'=>$pid);
} else {
$this->myChildren[] = array('time'=>$time,'pid'=>$pid);
}
}
}
public function killChild($pid = 0) {
if ($pid > 0) {
posix_kill($pid, SIGTERM);
if ($this->killCallback !== null) call_user_func($this->killCallback);
}
}
public function parentCheck() {
if ($this->myPID() == $this->parentPID) {
return true;
} else {
return false;
}
}
public function pidDead($pid = 0) {
if ($pid > 0) {
return pcntl_waitpid($pid, $status, WUNTRACED OR WNOHANG);
} else {
return 0;
}
}
public function setCallback($callback = null) {
$this->shutdownCallback = $callback;
}
public function setKillCallback($callback = null) {
$this->killCallback = $callback;
}
public function childCount() {
return count($this->myChildren);
}
public function runParentCode() {
if (!$this->complete) {
return $this->parentCheck();
} else {
if ($this->shutdownCallback !== null)
call_user_func($this->shutdownCallback);
return false;
}
}
public function runChildCode() {
return !$this->parentCheck();
}
public function spawnReady() {
if (count($this->myChildren) < $this->maxChildren) {
return true;
} else {
return false;
}
}
public function shutdown() {
while($this->childCount()) {
$this->checkChildren();
$this->tick();
}
$this->complete = true;
}
public function tick() {
usleep($this->sleepCount);
}
public function exec($proc, $args = null) {
if ($args == null) {
pcntl_exec($proc);
} else {
pcntl_exec($proc, $args);
}
}
}
?>