Skip to content

Commit 9c21b01

Browse files
[Process] Fix pipes handling
1 parent a1c95f7 commit 9c21b01

File tree

2 files changed

+44
-60
lines changed

2 files changed

+44
-60
lines changed

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

+23-25
Original file line numberDiff line numberDiff line change
@@ -113,20 +113,16 @@ public function readAndWrite($blocking, $close = false)
113113

114114
$this->unblock();
115115

116-
$read = array();
116+
$read = $e = array();
117+
$r = $this->pipes;
117118

118119
if (null !== $this->input) {
119-
// if input is a resource, let's add it to stream_select argument to
120-
// fill a buffer
121-
$r = array_merge($this->pipes, array('input' => $this->input));
122-
} else {
123-
$r = $this->pipes;
120+
$r['input'] = $this->input;
124121
}
125122
// discard read on stdin
126123
unset($r[0]);
127124

128-
$w = isset($this->pipes[0]) ? array($this->pipes[0]) : null;
129-
$e = null;
125+
$w = isset($this->pipes[0]) ? array($this->pipes[0]) : $e;
130126

131127
// let's have a look if something changed in streams
132128
if (false === $n = @stream_select($r, $w, $e, 0, $blocking ? Process::TIMEOUT_PRECISION * 1E6 : 0)) {
@@ -147,22 +143,17 @@ public function readAndWrite($blocking, $close = false)
147143
foreach ($r as $pipe) {
148144
// prior PHP 5.4 the array passed to stream_select is modified and
149145
// lose key association, we have to find back the key
150-
$type = (false !== $found = array_search($pipe, $this->pipes)) ? $found : 'input';
151-
$data = '';
152-
if ($type !== 'input') {
153-
while ('' !== $dataread = (string) fread($pipe, self::CHUNK_SIZE)) {
154-
$data .= $dataread;
155-
}
156-
// Remove extra null chars returned by fread
157-
if ('' !== $data) {
158-
$read[$type] = rtrim($data, "\x00");
146+
$type = (false !== $type = array_search($pipe, $this->pipes, true)) ? $type : 'input';
147+
$data = fread($pipe, self::CHUNK_SIZE);
148+
149+
if (isset($data[0])) {
150+
if ('input' !== $type) {
151+
$read[$type] = $data;
152+
} elseif (isset($this->pipes[0])) {
153+
$this->inputBuffer .= $data;
159154
}
160-
} elseif (isset($w[0])) {
161-
stream_copy_to_stream($this->input, $w[0], 4096);
162-
}
163-
164-
if (false === $data || (true === $close && feof($pipe) && '' === $data)) {
165-
if ($type === 'input') {
155+
} elseif (!isset($data[0]) && $close && feof($pipe)) {
156+
if ('input' === $type) {
166157
// no more data to read on input resource
167158
// use an empty buffer in the next reads
168159
$this->input = null;
@@ -173,8 +164,15 @@ public function readAndWrite($blocking, $close = false)
173164
}
174165
}
175166

176-
// no input to read on resource and stdin still open
177-
if (null === $this->input && isset($this->pipes[0])) {
167+
if (isset($this->inputBuffer[0])) {
168+
foreach ($w as $pipe) {
169+
$written = fwrite($pipe, $this->inputBuffer);
170+
$this->inputBuffer = substr($this->inputBuffer, $written);
171+
}
172+
}
173+
174+
// no input to read on resource, buffer is empty and stdin still open
175+
if (!isset($this->inputBuffer[0]) && null === $this->input && isset($this->pipes[0])) {
178176
fclose($this->pipes[0]);
179177
unset($this->pipes[0]);
180178
}

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

+21-35
Original file line numberDiff line numberDiff line change
@@ -52,16 +52,18 @@ public function __construct($disableOutput, $input)
5252
Process::STDERR => tempnam(sys_get_temp_dir(), 'err_sf_proc'),
5353
);
5454
foreach ($this->files as $offset => $file) {
55-
if (false === $file || false === $this->fileHandles[$offset] = fopen($file, 'rb')) {
55+
if (false === $file || false === $this->fileHandles[$offset] = @fopen($file, 'rb')) {
5656
throw new RuntimeException('A temporary file could not be opened to write the process output to, verify that your TEMP environment variable is writable');
5757
}
5858
}
5959
}
6060

6161
if (is_resource($input)) {
6262
$this->input = $input;
63-
} else {
63+
} elseif (is_string($input)) {
6464
$this->inputBuffer = $input;
65+
} else {
66+
$this->inputBuffer = (string) $input;
6567
}
6668
}
6769

@@ -117,19 +119,12 @@ public function readAndWrite($blocking, $close = false)
117119
if (0 !== fseek($fileHandle, $this->readBytes[$type])) {
118120
continue;
119121
}
120-
$data = '';
121-
$dataread = null;
122-
while (!feof($fileHandle)) {
123-
if (false !== $dataread = fread($fileHandle, self::CHUNK_SIZE)) {
124-
$data .= $dataread;
125-
}
126-
}
127-
if (0 < $length = strlen($data)) {
128-
$this->readBytes[$type] += $length;
129-
$read[$type] = $data;
130-
}
122+
$data = fread($fileHandle, self::CHUNK_SIZE);
131123

132-
if (false === $dataread || (true === $close && feof($fileHandle) && '' === $data)) {
124+
if (isset($data[0])) {
125+
$this->readBytes[$type] += strlen($data);
126+
$read[$type] = $data;
127+
} elseif ($close && feof($fileHandle)) {
133128
fclose($this->fileHandles[$type]);
134129
unset($this->fileHandles[$type]);
135130
}
@@ -143,7 +138,7 @@ public function readAndWrite($blocking, $close = false)
143138
*/
144139
public function areOpen()
145140
{
146-
return (bool) $this->pipes && (bool) $this->fileHandles;
141+
return $this->pipes && $this->fileHandles;
147142
}
148143

149144
/**
@@ -198,9 +193,9 @@ private function write($blocking, $close)
198193

199194
$this->unblock();
200195

201-
$r = null !== $this->input ? array('input' => $this->input) : null;
202-
$w = isset($this->pipes[0]) ? array($this->pipes[0]) : null;
203-
$e = null;
196+
$e = array();
197+
$r = null !== $this->input ? array('input' => $this->input) : $e;
198+
$w = isset($this->pipes[0]) ? array($this->pipes[0]) : $e;
204199

205200
// let's have a look if something changed in streams
206201
if (false === $n = @stream_select($r, $w, $e, 0, $blocking ? Process::TIMEOUT_PRECISION * 1E6 : 0)) {
@@ -218,34 +213,25 @@ private function write($blocking, $close)
218213
return;
219214
}
220215

221-
if (null !== $w && 0 < count($r)) {
222-
$data = '';
223-
while ($dataread = fread($r['input'], self::CHUNK_SIZE)) {
224-
$data .= $dataread;
225-
}
216+
foreach ($r as $pipe) {
217+
$this->inputBuffer .= $data = fread($pipe, self::CHUNK_SIZE);
226218

227-
$this->inputBuffer .= $data;
228-
229-
if (false === $data || (true === $close && feof($r['input']) && '' === $data)) {
219+
if (!isset($data[0]) && $close && feof($pipe)) {
230220
// no more data to read on input resource
231221
// use an empty buffer in the next reads
232222
$this->input = null;
233223
}
234224
}
235225

236-
if (null !== $w && 0 < count($w)) {
237-
while (strlen($this->inputBuffer)) {
238-
$written = fwrite($w[0], $this->inputBuffer, 2 << 18);
239-
if ($written > 0) {
240-
$this->inputBuffer = (string) substr($this->inputBuffer, $written);
241-
} else {
242-
break;
243-
}
226+
if (isset($this->inputBuffer[0])) {
227+
foreach ($w as $pipe) {
228+
$written = fwrite($pipe, $this->inputBuffer);
229+
$this->inputBuffer = substr($this->inputBuffer, $written);
244230
}
245231
}
246232

247233
// no input to read on resource, buffer is empty and stdin still open
248-
if ('' === $this->inputBuffer && null === $this->input && isset($this->pipes[0])) {
234+
if (!isset($this->inputBuffer[0]) && null === $this->input && isset($this->pipes[0])) {
249235
fclose($this->pipes[0]);
250236
unset($this->pipes[0]);
251237
}

0 commit comments

Comments
 (0)