public function readAndWrite($blocking, $close = false)
{
if (1 === count($this->pipes) && [0] === array_keys($this->pipes)) {
fclose($this->pipes[0]);
unset($this->pipes[0]);
}
if (empty($this->pipes)) {
return [];
}
$this->unblock();
$read = [];
if (null !== $this->input) {
$r = array_merge($this->pipes, ['input' => $this->input]);
} else {
$r = $this->pipes;
}
unset($r[0]);
$w = isset($this->pipes[0]) ? [$this->pipes[0]] : null;
$e = null;
if (false === ($n = @stream_select($r, $w, $e, 0, $blocking ? Process::TIMEOUT_PRECISION * 1000000.0 : 0))) {
if (!$this->hasSystemCallBeenInterrupted()) {
$this->pipes = [];
}
return $read;
}
if (0 === $n) {
return $read;
}
foreach ($r as $pipe) {
$type = false !== ($found = array_search($pipe, $this->pipes)) ? $found : 'input';
$data = '';
while ('' !== ($dataread = (string) fread($pipe, self::CHUNK_SIZE))) {
$data .= $dataread;
}
if ('' !== $data) {
if ($type === 'input') {
$this->inputBuffer .= $data;
} else {
$read[$type] = $data;
}
}
if (false === $data || true === $close && feof($pipe) && '' === $data) {
if ($type === 'input') {
$this->input = null;
} else {
fclose($this->pipes[$type]);
unset($this->pipes[$type]);
}
}
}
if (null !== $w && 0 < count($w)) {
while (strlen($this->inputBuffer)) {
$written = fwrite($w[0], $this->inputBuffer, 2 << 18);
// write 512k
if ($written > 0) {
$this->inputBuffer = (string) substr($this->inputBuffer, $written);
} else {
break;
}
}
}
if ('' === $this->inputBuffer && null === $this->input && isset($this->pipes[0])) {
fclose($this->pipes[0]);
unset($this->pipes[0]);
}
return $read;
}