Issues (25)

Security Analysis    no request data  

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

src/Process.php (4 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * Created by PhpStorm.
4
 * User: Jenner
5
 * Date: 2015/8/12
6
 * Time: 15:25
7
 */
8
9
namespace Jenner\SimpleFork;
10
11
class Process
12
{
13
    /**
14
     * @var Runnable|callable
15
     */
16
    protected $runnable;
17
18
    /**
19
     * @var int
20
     */
21
    protected $pid = 0;
22
23
    /**
24
     * @var string custom process name
25
     */
26
    protected $name = null;
27
28
    /**
29
     * @var bool if the process is started
30
     */
31
    protected $started = false;
32
33
    /**
34
     * @var bool
35
     */
36
    protected $running = false;
37
38
    /**
39
     * @var int the signal which made the process terminate
40
     */
41
    protected $term_signal = null;
42
43
    /**
44
     * @var int the signal which made the process stop
45
     */
46
    protected $stop_signal = null;
47
48
    /**
49
     * @var int error code
50
     */
51
    protected $errno = null;
52
53
    /**
54
     * @var string error message
55
     */
56
    protected $errmsg = null;
57
58
    /**
59
     * @var bool
60
     */
61
    protected $if_signal = false;
62
63
    /**
64
     * @var array
65
     */
66
    protected $callbacks = array();
67
68
    /**
69
     * @var array signal handlers
70
     */
71
    protected $signal_handlers = array();
72
73
74
    /**
75
     * @param string $execution it can be a Runnable object, callback function or null
76
     * @param null $name process name,you can manager the process by it's name.
77
     */
78 60
    public function __construct($execution = null, $name = null)
79
    {
80 60
        if (!is_null($execution) && $execution instanceof Runnable) {
81 9
            $this->runnable = $execution;
82 60
        } elseif (!is_null($execution) && is_callable($execution)) {
83 45
            $this->runnable = $execution;
84 54
        } elseif (!is_null($execution)) {
85
            throw new \InvalidArgumentException('param execution is not a object of Runnable or callable');
86
        } else {
87 12
            Utils::checkOverwriteRunMethod(get_class($this));
88
        }
89 57
        if (!is_null($name)) {
90 3
            $this->name = $name;
91 3
        }
92
93 57
        $this->initStatus();
94 57
    }
95
96
    /**
97
     * init process status
98
     */
99 57
    protected function initStatus()
100
    {
101 57
        $this->pid = null;
102 57
        $this->running = null;
103 57
        $this->term_signal = null;
104 57
        $this->stop_signal = null;
105 57
        $this->errno = null;
106 57
        $this->errmsg = null;
107 57
    }
108
109
    /**
110
     * get pid
111
     *
112
     * @return int
113
     */
114 9
    public function getPid()
115
    {
116 9
        return $this->pid;
117
    }
118
119
    /**
120
     * get or set name
121
     *
122
     * @param string|null $name
123
     * @return mixed
124
     */
125 3
    public function name($name = null)
126
    {
127 3
        if (!is_null($name)) {
128
            $this->name = $name;
129
        } else {
130 3
            return $this->name;
131
        }
132
    }
133
134
    /**
135
     * if the process is stopped
136
     *
137
     * @return bool
138
     */
139 3
    public function isStopped()
140
    {
141 3
        if (is_null($this->errno)) {
142 3
            return false;
143
        }
144
145 3
        return true;
146
    }
147
148
    /**
149
     * if the process is started
150
     *
151
     * @return bool
152
     */
153 15
    public function isStarted()
154
    {
155 15
        return $this->started;
156
    }
157
158
    /**
159
     * get pcntl errno
160
     *
161
     * @return int
162
     */
163 9
    public function errno()
164
    {
165 9
        return $this->errno;
166
    }
167
168
    /**
169
     * get pcntl errmsg
170
     *
171
     * @return string
172
     */
173 6
    public function errmsg()
174
    {
175 6
        return $this->errmsg;
176
    }
177
178 3
    public function ifSignal()
179
    {
180 3
        return $this->if_signal;
181
    }
182
183
    /**
184
     * start the sub process
185
     * and run the callback
186
     *
187
     * @return string pid
188
     */
189 54
    public function start()
190
    {
191 54
        if (!empty($this->pid) && $this->isRunning()) {
192
            throw new \LogicException("the process is already running");
193
        }
194
195 54
        $callback = $this->getCallable();
196
197 54
        $pid = pcntl_fork();
198 54
        if ($pid < 0) {
199
            throw new \RuntimeException("fork error");
200 54
        } elseif ($pid > 0) {
201 54
            $this->pid = $pid;
202 54
            $this->running = true;
203 54
            $this->started = true;
204 54
        } else {
205
            $this->pid = getmypid();
206
            $this->signal();
207
            foreach ($this->signal_handlers as $signal => $handler) {
208
                pcntl_signal($signal, $handler);
209
            }
210
            call_user_func($callback);
211
            exit(0);
0 ignored issues
show
Coding Style Compatibility introduced by
The method start() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
212
        }
213 54
    }
214
215
    /**
216
     * if the process is running
217
     *
218
     * @return bool
219
     */
220 54
    public function isRunning()
221
    {
222 54
        $this->updateStatus();
223 54
        return $this->running;
224
    }
225
226
    /**
227
     * update the process status
228
     *
229
     * @param bool $block
230
     */
231 54
    protected function updateStatus($block = false)
232
    {
233 54
        if ($this->running !== true) {
234 24
            return;
235
        }
236
237 54
        if ($block) {
238 12
            $res = pcntl_waitpid($this->pid, $status);
0 ignored issues
show
The variable $status does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
239 12
        } else {
240 54
            $res = pcntl_waitpid($this->pid, $status, WNOHANG | WUNTRACED);
241
        }
242
243 54
        if ($res === -1) {
244
            throw new \RuntimeException('pcntl_waitpid failed. the process maybe available');
245 54
        } elseif ($res === 0) {
246 54
            $this->running = true;
247 54
        } else {
248 51
            if (pcntl_wifsignaled($status)) {
249 6
                $this->term_signal = pcntl_wtermsig($status);
250 6
            }
251 51
            if (pcntl_wifstopped($status)) {
252
                $this->stop_signal = pcntl_wstopsig($status);
253
            }
254 51
            if (pcntl_wifexited($status)) {
255 45
                $this->errno = pcntl_wexitstatus($status);
256 45
                $this->errmsg = pcntl_strerror($this->errno);
257 45
            } else {
258 6
                $this->errno = pcntl_get_last_error();
259 6
                $this->errmsg = pcntl_strerror($this->errno);
260
            }
261 51
            if (pcntl_wifsignaled($status)) {
262 6
                $this->if_signal = true;
263 6
            } else {
264 45
                $this->if_signal = false;
265
            }
266
267 51
            $this->running = false;
268
        }
269 54
    }
270
271
    /**
272
     * get sub process callback
273
     *
274
     * @return array|callable|null
275
     */
276 54
    protected function getCallable()
277
    {
278 54
        $callback = null;
0 ignored issues
show
$callback is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
279 54
        if (is_object($this->runnable) && $this->runnable instanceof Runnable) {
280 9
            $callback = array($this->runnable, 'run');
281 54
        } elseif (is_callable($this->runnable)) {
282 45
            $callback = $this->runnable;
283 45
        } else {
284 6
            $callback = array($this, 'run');
285
        }
286
287 54
        return $callback;
288
    }
289
290
    /**
291
     * register signal SIGTERM handler,
292
     * when the parent process call shutdown and use the default signal,
293
     * this handler will be triggered
294
     */
295
    protected function signal()
296
    {
297
        pcntl_signal(SIGTERM, function () {
298
            exit(0);
0 ignored issues
show
Coding Style Compatibility introduced by
The method signal() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
299
        });
300
    }
301
302
    /**
303
     * kill self
304
     *
305
     * @param bool|true $block
306
     * @param int $signal
307
     */
308 12
    public function shutdown($block = true, $signal = SIGTERM)
309
    {
310 12
        if (empty($this->pid)) {
311
            throw new \LogicException('the process pid is null, so maybe the process is not started');
312
        }
313 12
        if (!$this->isRunning()) {
314
            throw new \LogicException("the process is not running");
315
        }
316 12
        if (!posix_kill($this->pid, $signal)) {
317
            throw new \RuntimeException("kill son process failed");
318
        }
319
320 12
        $this->updateStatus($block);
321 12
    }
322
323
    /**
324
     * waiting for the sub process exit
325
     *
326
     * @param bool|true $block if block the process
327
     * @param int $sleep default 0.1s check sub process status
328
     * every $sleep milliseconds.
329
     */
330 33
    public function wait($block = true, $sleep = 100000)
331
    {
332 33
        while (true) {
333 33
            if ($this->isRunning() === false) {
334 33
                return;
335
            }
336 30
            if (!$block) {
337
                break;
338
            }
339 30
            usleep($sleep);
340 30
        }
341
    }
342
343
    /**
344
     * register sub process signal handler,
345
     * when the sub process start, the handlers will be registered
346
     *
347
     * @param $signal
348
     * @param callable $handler
349
     */
350
    public function registerSignalHandler($signal, callable $handler)
351
    {
352
        $this->signal_handlers[$signal] = $handler;
353
    }
354
355
    /**
356
     * after php-5.3.0, we can call pcntl_singal_dispatch to call signal handlers for pending signals
357
     * which can save cpu resources than using declare(tick=n)
358
     *
359
     * @return bool
360
     */
361
    public function dispatchSignal()
362
    {
363
        return pcntl_signal_dispatch();
364
    }
365
366
    /**
367
     * you should overwrite this function
368
     * if you do not use the Runnable or callback.
369
     */
370
    public function run()
371
    {
372
    }
373
}