PluginProbe ʕ •ᴥ•ʔ
WP STAGING – WordPress Backups, Restore, Migration & Clone / 4.11.0
WP STAGING – WordPress Backups, Restore, Migration & Clone v4.11.0
4.11.0 4.10.0 4.9.5 4.9.4 4.9.3 4.9.2 4.9.1 4.9.0 4.8.1 trunk 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.1.0 3.1.1 3.1.2 3.1.3 3.1.4 3.10.0 3.2.0 3.3.1 3.3.2 3.3.3 3.4.1 3.4.3 3.5.0 3.6.0 3.7.1 3.8.0 3.8.1 3.8.2 3.8.3 3.8.4 3.8.5 3.8.6 3.8.7 3.9.0 3.9.1 3.9.2 3.9.3 3.9.4 4.0.0 4.1.0 4.1.1 4.1.2 4.1.3 4.1.4 4.2.0 4.2.1 4.3.0 4.3.1 4.3.2 4.4.0 4.5.0 4.6.0 4.7.0 4.7.1 4.7.2 4.7.3 4.8.0
wp-staging / Framework / Job / ProcessLock.php
wp-staging / Framework / Job Last commit date
Ajax 1 day ago BackgroundProcessing 1 day ago Dto 1 day ago Exception 1 day ago Interfaces 1 day ago Jobs 1 day ago Task 1 day ago Traits 10 months ago AbstractJob.php 1 day ago JobProvider.php 1 day ago JobServiceProvider.php 1 day ago JobTransientCache.php 1 day ago ProcessLock.php 1 day ago
ProcessLock.php
230 lines
1 <?php
2
3 namespace WPStaging\Framework\Job;
4
5 use RuntimeException;
6 use WPStaging\Core\WPStaging;
7 use WPStaging\Framework\Job\Exception\ProcessLockedException;
8 use WPStaging\Framework\Traits\ResourceTrait;
9
10 class ProcessLock
11 {
12 use ResourceTrait;
13
14 const LOCK_FILE_NAME = '.wpstg_process_locked';
15
16
17 private $lockFile;
18
19
20
21
22
23
24
25
26
27
28
29
30 private static $handle = null;
31
32 public function __construct()
33 {
34 $this->lockFile = trailingslashit(WPStaging::getContentDir()) . self::LOCK_FILE_NAME;
35 }
36
37
38
39
40
41
42
43
44
45
46
47
48
49 public function lockProcess()
50 {
51
52
53 if (self::$handle !== null) {
54 return;
55 }
56
57 $handle = $this->openLockFile();
58
59 if (!$this->acquireHandle($handle)) {
60 fclose($handle);
61
62 throw ProcessLockedException::processAlreadyLocked();
63 }
64
65 $this->writeLockedAt($handle);
66
67 self::$handle = $handle;
68 }
69
70
71
72
73
74
75 public function unlockProcess()
76 {
77 $handle = self::$handle;
78
79 if ($handle === null) {
80 return;
81 }
82
83 self::$handle = null;
84
85
86
87
88 ftruncate($handle, 0);
89 flock($handle, LOCK_UN);
90 fclose($handle);
91 }
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107 public function checkProcessLocked($timeout = null)
108 {
109 if (self::$handle !== null) {
110 return;
111 }
112
113 $handle = $this->openLockFile();
114 $wouldBlock = 0;
115
116
117
118 if (flock($handle, LOCK_SH | LOCK_NB, $wouldBlock)) {
119 flock($handle, LOCK_UN);
120 fclose($handle);
121
122 return;
123 }
124
125 fclose($handle);
126
127 if ($wouldBlock || !$this->isLockRecordStale($timeout)) {
128 throw ProcessLockedException::processAlreadyLocked();
129 }
130 }
131
132
133
134
135
136 private function acquireHandle($handle): bool
137 {
138 $wouldBlock = 0;
139
140 if (flock($handle, LOCK_EX | LOCK_NB, $wouldBlock)) {
141 return true;
142 }
143
144
145
146
147
148 if ($wouldBlock) {
149 return false;
150 }
151
152 return $this->isLockRecordStale();
153 }
154
155
156
157
158
159
160
161
162
163 private function writeLockedAt($handle)
164 {
165 $lockedAt = (string)time();
166
167 ftruncate($handle, 0);
168 rewind($handle);
169
170 if (fwrite($handle, $lockedAt) !== strlen($lockedAt)) {
171 ftruncate($handle, 0);
172 }
173
174 fflush($handle);
175 }
176
177
178
179
180
181 private function isLockRecordStale($timeout = null): bool
182 {
183 if (is_null($timeout)) {
184 $timeout = min(120, $this->getTimeLimit());
185 }
186
187 if (!file_exists($this->lockFile)) {
188 return true;
189 }
190
191 $lockedAt = file_get_contents($this->lockFile);
192
193
194
195 if (!is_numeric($lockedAt)) {
196 return true;
197 }
198
199 return (int)$lockedAt < time() - $timeout;
200 }
201
202
203
204
205
206 private function openLockFile()
207 {
208
209
210 $error = '';
211 set_error_handler(function ($errno, $errstr) use (&$error) {
212 $error = $errstr;
213
214 return true;
215 });
216
217
218
219 $handle = fopen($this->lockFile, 'c+');
220
221 restore_error_handler();
222
223 if ($handle === false) {
224 throw new RuntimeException(sprintf('Could not open the process lock file %s. %s', $this->lockFile, $error));
225 }
226
227 return $handle;
228 }
229 }
230