Skip to content

Commit 9fdc64b

Browse files
committed
bug symfony#28689 [Process] fix locking of pipe files on Windows (nicolas-grekas)
This PR was merged into the 2.8 branch. Discussion ---------- [Process] fix locking of pipe files on Windows | Q | A | ------------- | --- | Branch? | 2.8 | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | symfony#28655 | License | MIT | Doc PR | - Commits ------- d64bd3b [Process] fix locking of pipe files on Windows
2 parents 270f496 + d64bd3b commit 9fdc64b

File tree

1 file changed

+26
-31
lines changed

1 file changed

+26
-31
lines changed

src/Symfony/Component/Process/Pipes/WindowsPipes.php

Lines changed: 26 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ class WindowsPipes extends AbstractPipes
2828
{
2929
private $files = array();
3030
private $fileHandles = array();
31+
private $lockHandles = array();
3132
private $readBytes = array(
3233
Process::STDOUT => 0,
3334
Process::STDERR => 0,
@@ -47,31 +48,33 @@ public function __construct($disableOutput, $input)
4748
Process::STDOUT => Process::OUT,
4849
Process::STDERR => Process::ERR,
4950
);
50-
$tmpCheck = false;
5151
$tmpDir = sys_get_temp_dir();
5252
$lastError = 'unknown reason';
5353
set_error_handler(function ($type, $msg) use (&$lastError) { $lastError = $msg; });
5454
for ($i = 0;; ++$i) {
5555
foreach ($pipes as $pipe => $name) {
5656
$file = sprintf('%s\\sf_proc_%02X.%s', $tmpDir, $i, $name);
57-
if (file_exists($file) && !unlink($file)) {
58-
continue 2;
59-
}
60-
$h = fopen($file, 'xb');
61-
if (!$h) {
62-
$error = $lastError;
63-
if ($tmpCheck || $tmpCheck = unlink(tempnam(false, 'sf_check_'))) {
64-
continue;
65-
}
57+
58+
if (!$h = fopen($file.'.lock', 'w')) {
6659
restore_error_handler();
67-
throw new RuntimeException(sprintf('A temporary file could not be opened to write the process output: %s', $error));
60+
throw new RuntimeException(sprintf('A temporary file could not be opened to write the process output: %s', $lastError));
6861
}
69-
if (!$h || !$this->fileHandles[$pipe] = fopen($file, 'rb')) {
62+
if (!flock($h, LOCK_EX | LOCK_NB)) {
7063
continue 2;
7164
}
72-
if (isset($this->files[$pipe])) {
73-
unlink($this->files[$pipe]);
65+
if (isset($this->lockHandles[$pipe])) {
66+
flock($this->lockHandles[$pipe], LOCK_UN);
67+
fclose($this->lockHandles[$pipe]);
7468
}
69+
$this->lockHandles[$pipe] = $h;
70+
71+
if (!fclose(fopen($file, 'w')) || !$h = fopen($file, 'r')) {
72+
flock($this->lockHandles[$pipe], LOCK_UN);
73+
fclose($this->lockHandles[$pipe]);
74+
unset($this->lockHandles[$pipe]);
75+
continue 2;
76+
}
77+
$this->fileHandles[$pipe] = $h;
7578
$this->files[$pipe] = $file;
7679
}
7780
break;
@@ -85,7 +88,6 @@ public function __construct($disableOutput, $input)
8588
public function __destruct()
8689
{
8790
$this->close();
88-
$this->removeFiles();
8991
}
9092

9193
/**
@@ -145,8 +147,11 @@ public function readAndWrite($blocking, $close = false)
145147
$read[$type] = $data;
146148
}
147149
if ($close) {
150+
ftruncate($fileHandle, 0);
148151
fclose($fileHandle);
149-
unset($this->fileHandles[$type]);
152+
flock($this->lockHandles[$type], LOCK_UN);
153+
fclose($this->lockHandles[$type]);
154+
unset($this->fileHandles[$type], $this->lockHandles[$type]);
150155
}
151156
}
152157

@@ -167,10 +172,13 @@ public function areOpen()
167172
public function close()
168173
{
169174
parent::close();
170-
foreach ($this->fileHandles as $handle) {
175+
foreach ($this->fileHandles as $type => $handle) {
176+
ftruncate($handle, 0);
171177
fclose($handle);
178+
flock($this->lockHandles[$type], LOCK_UN);
179+
fclose($this->lockHandles[$type]);
172180
}
173-
$this->fileHandles = array();
181+
$this->fileHandles = $this->lockHandles = array();
174182
}
175183

176184
/**
@@ -185,17 +193,4 @@ public static function create(Process $process, $input)
185193
{
186194
return new static($process->isOutputDisabled(), $input);
187195
}
188-
189-
/**
190-
* Removes temporary files.
191-
*/
192-
private function removeFiles()
193-
{
194-
foreach ($this->files as $filename) {
195-
if (file_exists($filename)) {
196-
@unlink($filename);
197-
}
198-
}
199-
$this->files = array();
200-
}
201196
}

0 commit comments

Comments
 (0)