annotate vendor/symfony/process/Pipes/AbstractPipes.php @ 14:1fec387a4317

Update Drupal core to 8.5.2 via Composer
author Chris Cannam
date Mon, 23 Apr 2018 09:46:53 +0100
parents 4c8ae668cc8c
children c2387f117808
rev   line source
Chris@0 1 <?php
Chris@0 2
Chris@0 3 /*
Chris@0 4 * This file is part of the Symfony package.
Chris@0 5 *
Chris@0 6 * (c) Fabien Potencier <fabien@symfony.com>
Chris@0 7 *
Chris@0 8 * For the full copyright and license information, please view the LICENSE
Chris@0 9 * file that was distributed with this source code.
Chris@0 10 */
Chris@0 11
Chris@0 12 namespace Symfony\Component\Process\Pipes;
Chris@0 13
Chris@0 14 use Symfony\Component\Process\Exception\InvalidArgumentException;
Chris@0 15
Chris@0 16 /**
Chris@0 17 * @author Romain Neutron <imprec@gmail.com>
Chris@0 18 *
Chris@0 19 * @internal
Chris@0 20 */
Chris@0 21 abstract class AbstractPipes implements PipesInterface
Chris@0 22 {
Chris@0 23 public $pipes = array();
Chris@0 24
Chris@0 25 private $inputBuffer = '';
Chris@0 26 private $input;
Chris@0 27 private $blocked = true;
Chris@0 28
Chris@14 29 /**
Chris@14 30 * @param resource|string|int|float|bool|\Iterator|null $input
Chris@14 31 */
Chris@0 32 public function __construct($input)
Chris@0 33 {
Chris@0 34 if (is_resource($input) || $input instanceof \Iterator) {
Chris@0 35 $this->input = $input;
Chris@0 36 } elseif (is_string($input)) {
Chris@0 37 $this->inputBuffer = $input;
Chris@0 38 } else {
Chris@0 39 $this->inputBuffer = (string) $input;
Chris@0 40 }
Chris@0 41 }
Chris@0 42
Chris@0 43 /**
Chris@0 44 * {@inheritdoc}
Chris@0 45 */
Chris@0 46 public function close()
Chris@0 47 {
Chris@0 48 foreach ($this->pipes as $pipe) {
Chris@0 49 fclose($pipe);
Chris@0 50 }
Chris@0 51 $this->pipes = array();
Chris@0 52 }
Chris@0 53
Chris@0 54 /**
Chris@0 55 * Returns true if a system call has been interrupted.
Chris@0 56 *
Chris@0 57 * @return bool
Chris@0 58 */
Chris@0 59 protected function hasSystemCallBeenInterrupted()
Chris@0 60 {
Chris@0 61 $lastError = error_get_last();
Chris@0 62
Chris@0 63 // stream_select returns false when the `select` system call is interrupted by an incoming signal
Chris@0 64 return isset($lastError['message']) && false !== stripos($lastError['message'], 'interrupted system call');
Chris@0 65 }
Chris@0 66
Chris@0 67 /**
Chris@0 68 * Unblocks streams.
Chris@0 69 */
Chris@0 70 protected function unblock()
Chris@0 71 {
Chris@0 72 if (!$this->blocked) {
Chris@0 73 return;
Chris@0 74 }
Chris@0 75
Chris@0 76 foreach ($this->pipes as $pipe) {
Chris@0 77 stream_set_blocking($pipe, 0);
Chris@0 78 }
Chris@0 79 if (is_resource($this->input)) {
Chris@0 80 stream_set_blocking($this->input, 0);
Chris@0 81 }
Chris@0 82
Chris@0 83 $this->blocked = false;
Chris@0 84 }
Chris@0 85
Chris@0 86 /**
Chris@0 87 * Writes input to stdin.
Chris@0 88 *
Chris@0 89 * @throws InvalidArgumentException When an input iterator yields a non supported value
Chris@0 90 */
Chris@0 91 protected function write()
Chris@0 92 {
Chris@0 93 if (!isset($this->pipes[0])) {
Chris@0 94 return;
Chris@0 95 }
Chris@0 96 $input = $this->input;
Chris@0 97
Chris@0 98 if ($input instanceof \Iterator) {
Chris@0 99 if (!$input->valid()) {
Chris@0 100 $input = null;
Chris@0 101 } elseif (is_resource($input = $input->current())) {
Chris@0 102 stream_set_blocking($input, 0);
Chris@0 103 } elseif (!isset($this->inputBuffer[0])) {
Chris@0 104 if (!is_string($input)) {
Chris@0 105 if (!is_scalar($input)) {
Chris@0 106 throw new InvalidArgumentException(sprintf('%s yielded a value of type "%s", but only scalars and stream resources are supported', get_class($this->input), gettype($input)));
Chris@0 107 }
Chris@0 108 $input = (string) $input;
Chris@0 109 }
Chris@0 110 $this->inputBuffer = $input;
Chris@0 111 $this->input->next();
Chris@0 112 $input = null;
Chris@0 113 } else {
Chris@0 114 $input = null;
Chris@0 115 }
Chris@0 116 }
Chris@0 117
Chris@0 118 $r = $e = array();
Chris@0 119 $w = array($this->pipes[0]);
Chris@0 120
Chris@0 121 // let's have a look if something changed in streams
Chris@14 122 if (false === @stream_select($r, $w, $e, 0, 0)) {
Chris@0 123 return;
Chris@0 124 }
Chris@0 125
Chris@0 126 foreach ($w as $stdin) {
Chris@0 127 if (isset($this->inputBuffer[0])) {
Chris@0 128 $written = fwrite($stdin, $this->inputBuffer);
Chris@0 129 $this->inputBuffer = substr($this->inputBuffer, $written);
Chris@0 130 if (isset($this->inputBuffer[0])) {
Chris@0 131 return array($this->pipes[0]);
Chris@0 132 }
Chris@0 133 }
Chris@0 134
Chris@0 135 if ($input) {
Chris@0 136 for (;;) {
Chris@0 137 $data = fread($input, self::CHUNK_SIZE);
Chris@0 138 if (!isset($data[0])) {
Chris@0 139 break;
Chris@0 140 }
Chris@0 141 $written = fwrite($stdin, $data);
Chris@0 142 $data = substr($data, $written);
Chris@0 143 if (isset($data[0])) {
Chris@0 144 $this->inputBuffer = $data;
Chris@0 145
Chris@0 146 return array($this->pipes[0]);
Chris@0 147 }
Chris@0 148 }
Chris@0 149 if (feof($input)) {
Chris@0 150 if ($this->input instanceof \Iterator) {
Chris@0 151 $this->input->next();
Chris@0 152 } else {
Chris@0 153 $this->input = null;
Chris@0 154 }
Chris@0 155 }
Chris@0 156 }
Chris@0 157 }
Chris@0 158
Chris@0 159 // no input to read on resource, buffer is empty
Chris@0 160 if (!isset($this->inputBuffer[0]) && !($this->input instanceof \Iterator ? $this->input->valid() : $this->input)) {
Chris@0 161 $this->input = null;
Chris@0 162 fclose($this->pipes[0]);
Chris@0 163 unset($this->pipes[0]);
Chris@0 164 } elseif (!$w) {
Chris@0 165 return array($this->pipes[0]);
Chris@0 166 }
Chris@0 167 }
Chris@0 168 }