Passed
Pull Request — master (#96)
by Shinji
01:40
created

TraceeExecutor::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 0

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 1
eloc 0
c 1
b 0
f 1
nc 1
nop 5
dl 0
loc 7
rs 10
1
<?php
2
3
/**
4
 * This file is part of the sj-i/php-profiler package.
5
 *
6
 * (c) sji <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace PhpProfiler\Lib\Process\Exec;
15
16
use PhpProfiler\Lib\Libc\Errno\Errno;
17
use PhpProfiler\Lib\Libc\Sys\Ptrace\Ptrace;
18
use PhpProfiler\Lib\Libc\Sys\Ptrace\PtraceRequest;
19
use PhpProfiler\Lib\Libc\Unistd\Execvp;
20
use PhpProfiler\Lib\Process\Exec\Internal\Pcntl;
21
use PhpProfiler\Lib\System\OnShutdown;
22
23
class TraceeExecutor
24
{
25
    public function __construct(
26
        private Pcntl $pcntl,
27
        private Ptrace $ptrace,
28
        private Execvp $execvp,
29
        private Errno $errno,
30
        private OnShutdown $on_shutdown,
31
    ) {
32
    }
33
34
    /** @param list<string> $argv */
0 ignored issues
show
Bug introduced by
The type PhpProfiler\Lib\Process\Exec\list was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
35
    public function execute(string $command, array $argv): int
36
    {
37
        $pid = $this->pcntl->fork();
38
        if ($pid === 0) {
39
            $this->ptrace->ptrace(
40
                PtraceRequest::PTRACE_PTRACEME(),
41
                0,
42
                null,
43
                null
44
            );
45
            $result = $this->execvp->execvp($command, $argv);
46
            throw new TraceeExecutorException(
47
                "error on executing child process ({$result})({$this->errno->get()})"
48
            );
49
        } elseif ($pid < 0) {
50
            throw new TraceeExecutorException(
51
                "error on forking child process ({$this->errno->get()})"
52
            );
53
        }
54
        $this->pcntl->waitpid($pid, $status, WUNTRACED);
55
56
        if (!$this->pcntl->wifstopped($status)) {
57
            throw new TraceeExecutorException(
58
                "cannot stop child process"
59
            );
60
        }
61
        if ($this->pcntl->wstopsig($status) !== \SIGTRAP) {
62
            $signal = $this->pcntl->wstopsig($status);
63
            throw new TraceeExecutorException(
64
                "unexpected signal ({$signal})"
65
            );
66
        }
67
68
        $this->ptrace->ptrace(
69
            PtraceRequest::PTRACE_DETACH(),
70
            $pid,
71
            0,
72
            0
73
        );
74
75
        $this->on_shutdown->register(
76
            function () use ($pid) {
77
                $this->pcntl->waitpid($pid, $status, 0);
78
            }
79
        );
80
        return $pid;
81
    }
82
}
83