4 * This file is part of the Symfony package.
6 * (c) Fabien Potencier <fabien@symfony.com>
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
12 namespace Symfony\Component\Process\Pipes;
15 * @author Romain Neutron <imprec@gmail.com>
19 abstract class AbstractPipes implements PipesInterface
22 public $pipes = array();
25 private $inputBuffer = '';
26 /** @var resource|null */
29 private $blocked = true;
31 public function __construct($input)
33 if (is_resource($input)) {
34 $this->input = $input;
35 } elseif (is_string($input)) {
36 $this->inputBuffer = $input;
38 $this->inputBuffer = (string) $input;
45 public function close()
47 foreach ($this->pipes as $pipe) {
50 $this->pipes = array();
54 * Returns true if a system call has been interrupted.
58 protected function hasSystemCallBeenInterrupted()
60 $lastError = error_get_last();
62 // stream_select returns false when the `select` system call is interrupted by an incoming signal
63 return isset($lastError['message']) && false !== stripos($lastError['message'], 'interrupted system call');
69 protected function unblock()
71 if (!$this->blocked) {
75 foreach ($this->pipes as $pipe) {
76 stream_set_blocking($pipe, 0);
78 if (null !== $this->input) {
79 stream_set_blocking($this->input, 0);
82 $this->blocked = false;
86 * Writes input to stdin.
88 protected function write()
90 if (!isset($this->pipes[0])) {
93 $input = $this->input;
95 $w = array($this->pipes[0]);
97 // let's have a look if something changed in streams
98 if (false === $n = @stream_select($r, $w, $e, 0, 0)) {
102 foreach ($w as $stdin) {
103 if (isset($this->inputBuffer[0])) {
104 $written = fwrite($stdin, $this->inputBuffer);
105 $this->inputBuffer = substr($this->inputBuffer, $written);
106 if (isset($this->inputBuffer[0])) {
107 return array($this->pipes[0]);
113 $data = fread($input, self::CHUNK_SIZE);
114 if (!isset($data[0])) {
117 $written = fwrite($stdin, $data);
118 $data = substr($data, $written);
119 if (isset($data[0])) {
120 $this->inputBuffer = $data;
122 return array($this->pipes[0]);
126 // no more data to read on input resource
127 // use an empty buffer in the next reads
133 // no input to read on resource, buffer is empty
134 if (null === $this->input && !isset($this->inputBuffer[0])) {
135 fclose($this->pipes[0]);
136 unset($this->pipes[0]);
138 return array($this->pipes[0]);