Completed
Push — master ( 57fcfe...4c8185 )
by Andrew
11s
created

DaemonTrait::considerStatusCodes()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 13
rs 8.8571
cc 5
eloc 7
nc 4
nop 1
1
<?php
2
3
namespace PHPFastCGI\FastCGIDaemon;
4
5
use PHPFastCGI\FastCGIDaemon\Exception\ShutdownException;
6
7
trait DaemonTrait
8
{
9
    /**
10
     * @var bool
11
     */
12
    private $isShutdown = false;
13
14
    /**
15
     * @var string
16
     */
17
    private $shutdownMessage = '';
18
19
    /**
20
     * @var int
21
     */
22
    private $requestCount;
23
24
    /**
25
     * @var int
26
     */
27
    private $requestLimit;
28
29
    /**
30
     * @var int
31
     */
32
    private $memoryLimit;
33
34
    /**
35
     * @var bool
36
     */
37
    private $autoShutdown;
38
39
    /**
40
     * Flags the daemon for shutting down.
41
     * 
42
     * @param string $message Optional shutdown message
43
     */
44
    public function flagShutdown($message = null)
45
    {
46
        $this->isShutdown = true;
47
        $this->shutdownMessage = (null === $message ? 'Daemon flagged for shutdown' : $message);
48
    }
49
50
    /**
51
     * Loads to configuration from the daemon options and installs signal
52
     * handlers.
53
     *
54
     * @param DaemonOptions $daemonOptions
55
     */
56
    private function setupDaemon(DaemonOptions $daemonOptions)
57
    {
58
        $this->requestCount = 0;
59
        $this->requestLimit = $daemonOptions->getOption(DaemonOptions::REQUEST_LIMIT);
60
        $this->memoryLimit  = $daemonOptions->getOption(DaemonOptions::MEMORY_LIMIT);
61
        $this->autoShutdown = $daemonOptions->getOption(DaemonOptions::AUTO_SHUTDOWN);
62
63
        $timeLimit = $daemonOptions->getOption(DaemonOptions::TIME_LIMIT);
64
65
        if (DaemonOptions::NO_LIMIT !== $timeLimit) {
66
            pcntl_alarm($timeLimit);
67
        }
68
69
        $this->installSignalHandlers();
70
    }
71
72
    /**
73
     * Increments the request count and looks for application errors.
74
     *
75
     * @param int[] $statusCodes The status codes of sent responses
76
     */
77
    private function considerStatusCodes($statusCodes)
78
    {
79
        $this->requestCount += count($statusCodes);
80
81
        if ($this->autoShutdown) {
82
            foreach ($statusCodes as $statusCode) {
83
                if ($statusCode >= 500 && $statusCode < 600) {
84
                    $this->flagShutdown('Automatic shutdown following status code: ' . $statusCode);
85
                    break;
86
                }
87
            }
88
        }
89
    }
90
91
    /**
92
     * Installs a handler which throws a ShutdownException upon receiving a
93
     * SIGINT or a SIGALRM.
94
     *
95
     * @throws ShutdownException On receiving a SIGINT or SIGALRM
96
     */
97
    private function installSignalHandlers()
98
    {
99
        declare (ticks = 1);
100
101
        pcntl_signal(SIGINT, function () {
102
            throw new ShutdownException('Daemon shutdown requested (received SIGINT)');
103
        });
104
105
        pcntl_signal(SIGALRM, function () {
106
            throw new ShutdownException('Daemon time limit reached (received SIGALRM)');
107
        });
108
    }
109
110
    /**
111
     * Checks the current PHP process against the limits specified in a daemon
112
     * options object. This function will also throw an exception if the daemon
113
     * has been flagged for shutdown.
114
     *
115
     * @throws ShutdownException When limits in the daemon options are exceeded
116
     */
117
    private function checkDaemonLimits()
118
    {
119
        if ($this->isShutdown) {
120
            throw new ShutdownException($this->shutdownMessage);
121
        }
122
123
        pcntl_signal_dispatch();
124
125
        if (DaemonOptions::NO_LIMIT !== $this->requestLimit) {
126
            if ($this->requestLimit <= $this->requestCount) {
127
                throw new ShutdownException('Daemon request limit reached ('.$this->requestCount.' of '.$this->requestLimit.')');
128
            }
129
        }
130
131
        if (DaemonOptions::NO_LIMIT !== $this->memoryLimit) {
132
            $memoryUsage = memory_get_usage(true);
133
134
            if ($this->memoryLimit <= $memoryUsage) {
135
                throw new ShutdownException('Daemon memory limit reached ('.$memoryUsage.' of '.$this->memoryLimit.' bytes)');
136
            }
137
        }
138
    }
139
}
140