-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathProcessManager.php
158 lines (138 loc) · 5.82 KB
/
ProcessManager.php
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
<?php
namespace ProcessManager;
use ProcessManager\db\DBManagerInterface;
use ProcessManager\process\ProcessAbstract;
use ProcessManager\process\ProcessInterface;
use ProcessManager\process\ProcessParent;
class ProcessManager extends ProcessParent
{
/** @var integer number processes are running now */
protected $nRunningProcesses;
private $isStopSignal = false;
public function initSignalsHandlers()
{
pcntl_signal(SIGTERM, [$this, 'signalsHandlers']); //kill
pcntl_signal(SIGINT, [$this, 'signalsHandlers']); //ctrl+c
pcntl_signal(SIGHUP, [$this, 'signalsHandlers']); //restart process
// pcntl_signal(SIGCHLD, [$this, 'signalsHandlers']);
}
public function signalsHandlers($signo, $signinfo)
{
echo PHP_EOL . ' --- process ' . $this->getProcessName() . ' got signal=' . $signo . ' and signinfo='
. print_r($signinfo, true);
switch ($signo) {
case SIGINT:
case SIGTERM:
case SIGHUP:
$this->isStopSignal = true;
foreach ($this->getProcessRoulette() as $process) {
/** @var ProcessInterface|ProcessAbstract $process */
if ($process->isRunning()) {
$processPid = $process->getPid();
posix_kill($processPid, SIGTERM);
echo PHP_EOL . ' --- To process \'' . $process->getProcessName() . '\' sent TERMINATE signal';
}
}
break;
default:
}
}
public function start()
{
echo PHP_EOL . date('Y-m-d H:i:s') . ' PROCESS_MANAGER is started';
$this->updateProcessPriority();
$this->initSignalsHandlers();
$this->loadState();
if ($this->isStartNeeded() && !$this->isStopSignal) {//need run
$this->setPid(getmypid())
->saveState();
while (!$this->isStopNeeded() && !$this->isStopSignal) {
$this->setLastUpdateDatetime(date('Y-m-d H:i:s'))
->setRunningFlag(1)
->saveState();
// echo PHP_EOL . $this->getLastUpdateDatetime() . ' PROCESS_MANAGER is running';
//calculate number of running processes before
$nRunningProcesses = 0;
foreach ($this->getProcessRoulette() as $process) {
/** @var ProcessInterface|ProcessAbstract $process */
$process->loadState();
if ($process->isRunning()) {
$nRunningProcesses++;
}
}
$this->nRunningProcesses = $nRunningProcesses;
//Roulette starts from last not executed process
foreach ($this->getProcessRoulette() as $process) {
/** @var ProcessInterface|ProcessAbstract $process */
if ($this->nRunningProcesses >= $this->getMaxRunningProcesses()) {
break;
}
try {
if ($process->isStartNeeded()) {
$pid = $this->forkProcess($process);
if ($pid > 0) {
$this->nRunningProcesses++;
}
} elseif ($process->isStopNeeded()) {
$s = posix_kill($process->getPid(), SIGTERM);
if (!$s) {
$process->setRunningFlag(0)
->saveState();
}
}
} catch (\Throwable $e) {
$msg = '"' . $e->getMessage() . '" ' . PHP_EOL . $e->getTraceAsString();
echo PHP_EOL . date('Y-m-d H:i:s') . ' process \'' . $process->getProcessName() . '\' got exception:'
. PHP_EOL . $msg;
$process->addErrorToList(date('Y-m-d H:i:s') . ' ' . $msg)
->saveState();
}
}
//catch children signals
$pid = 1;
while ($pid > 0) {
$pid = pcntl_waitpid(-1, $pidStatus, WNOHANG);
// if ($pid > 0) {
// if (pcntl_wifexited($pidStatus)) {
// $code = pcntl_wexitstatus($pidStatus);
// } else {
// }
// }
}
sleep(1);
pcntl_signal_dispatch();
$this->loadState();
}
//init connect to db
// get listeners list
$this->setRunningFlag(0)
->saveState();
echo PHP_EOL . date('Y-m-d H:i:s') . ' PROCESS_MANAGER is stopped';
} elseif (// need stop
$this->isRunning()
&& (
$this->getLastUpdateDatetime() !== null
&& time() >= (strtotime($this->getLastUpdateDatetime()) + $this->getMaxLifetimeWithoutResults())
)
&& $this->getExecutionStep() !== 0
&& ($this->getMaxNTriesOfRun() === 0 || $this->getNTriesOfRun() <= $this->getMaxNTriesOfRun())
) {
echo PHP_EOL . date('Y-m-d H:i:s') . ' PROCESS_MANAGER is stopping';
posix_kill($this->getPid(), SIGTERM);
$this->setRunningFlag(0)
->saveState();
} else {
echo PHP_EOL . date('Y-m-d H:i:s') . ' PROCESS_MANAGER was run before';
}
}
/**
* clear parent resourses in child process
*
* @return void
*/
public function clearParentResourcesAfterFork()
{
$this->setProcessesRoulette(null);
$this->setDBManager(null);
}
}