Skip to content

Commit 34cc895

Browse files
[Process] fix locking of pipe files on Windows
1 parent aea4a62 commit 34cc895

File tree

1 file changed

+26
-26
lines changed

1 file changed

+26
-26
lines changed

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

Lines changed: 26 additions & 26 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,
@@ -54,24 +55,31 @@ public function __construct($disableOutput, $input)
5455
for ($i = 0;; ++$i) {
5556
foreach ($pipes as $pipe => $name) {
5657
$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) {
58+
59+
if (!$h = fopen($file.'.lock', 'w')) {
6260
$error = $lastError;
6361
if ($tmpCheck || $tmpCheck = unlink(tempnam(false, 'sf_check_'))) {
64-
continue;
62+
continue 2;
6563
}
6664
restore_error_handler();
6765
throw new RuntimeException(sprintf('A temporary file could not be opened to write the process output: %s', $error));
6866
}
69-
if (!$h || !$this->fileHandles[$pipe] = fopen($file, 'rb')) {
67+
if (!flock($h, LOCK_EX | LOCK_NB)) {
7068
continue 2;
7169
}
72-
if (isset($this->files[$pipe])) {
73-
unlink($this->files[$pipe]);
70+
if (isset($this->lockHandles[$pipe])) {
71+
flock($this->lockHandles[$pipe], LOCK_UN);
72+
fclose($this->lockHandles[$pipe]);
7473
}
74+
$this->lockHandles[$pipe] = $h;
75+
76+
if (!$h = fopen($file, 'w+')) {
77+
flock($this->lockHandles[$pipe], LOCK_UN);
78+
fclose($this->lockHandles[$pipe]);
79+
unset($this->lockHandles[$pipe]);
80+
continue 2;
81+
}
82+
$this->fileHandles[$pipe] = $h;
7583
$this->files[$pipe] = $file;
7684
}
7785
break;
@@ -85,7 +93,6 @@ public function __construct($disableOutput, $input)
8593
public function __destruct()
8694
{
8795
$this->close();
88-
$this->removeFiles();
8996
}
9097

9198
/**
@@ -145,8 +152,11 @@ public function readAndWrite($blocking, $close = false)
145152
$read[$type] = $data;
146153
}
147154
if ($close) {
155+
ftruncate($fileHandle, 0);
148156
fclose($fileHandle);
149-
unset($this->fileHandles[$type]);
157+
flock($this->lockHandles[$type], LOCK_UN);
158+
fclose($this->lockHandles[$type]);
159+
unset($this->fileHandles[$type], $this->lockHandles[$type]);
150160
}
151161
}
152162

@@ -167,10 +177,13 @@ public function areOpen()
167177
public function close()
168178
{
169179
parent::close();
170-
foreach ($this->fileHandles as $handle) {
180+
foreach ($this->fileHandles as $type => $handle) {
181+
ftruncate($handle, 0);
171182
fclose($handle);
183+
flock($this->lockHandles[$type], LOCK_UN);
184+
fclose($this->lockHandles[$type]);
172185
}
173-
$this->fileHandles = array();
186+
$this->fileHandles = $this->lockHandles = array();
174187
}
175188

176189
/**
@@ -185,17 +198,4 @@ public static function create(Process $process, $input)
185198
{
186199
return new static($process->isOutputDisabled(), $input);
187200
}
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-
}
201201
}

0 commit comments

Comments
 (0)