[ Index ]

PHP Cross Reference of phpBB-3.3.14-deutsch

title

Body

[close]

/vendor/symfony/process/Pipes/ -> WindowsPipes.php (source)

   1  <?php
   2  
   3  /*
   4   * This file is part of the Symfony package.
   5   *
   6   * (c) Fabien Potencier <fabien@symfony.com>
   7   *
   8   * For the full copyright and license information, please view the LICENSE
   9   * file that was distributed with this source code.
  10   */
  11  
  12  namespace Symfony\Component\Process\Pipes;
  13  
  14  use Symfony\Component\Process\Exception\RuntimeException;
  15  use Symfony\Component\Process\Process;
  16  
  17  /**
  18   * WindowsPipes implementation uses temporary files as handles.
  19   *
  20   * @see https://bugs.php.net/51800
  21   * @see https://bugs.php.net/65650
  22   *
  23   * @author Romain Neutron <imprec@gmail.com>
  24   *
  25   * @internal
  26   */
  27  class WindowsPipes extends AbstractPipes
  28  {
  29      private $files = [];
  30      private $fileHandles = [];
  31      private $lockHandles = [];
  32      private $readBytes = [
  33          Process::STDOUT => 0,
  34          Process::STDERR => 0,
  35      ];
  36      private $haveReadSupport;
  37  
  38      public function __construct($input, $haveReadSupport)
  39      {
  40          $this->haveReadSupport = (bool) $haveReadSupport;
  41  
  42          if ($this->haveReadSupport) {
  43              // Fix for PHP bug #51800: reading from STDOUT pipe hangs forever on Windows if the output is too big.
  44              // Workaround for this problem is to use temporary files instead of pipes on Windows platform.
  45              //
  46              // @see https://bugs.php.net/51800
  47              $pipes = [
  48                  Process::STDOUT => Process::OUT,
  49                  Process::STDERR => Process::ERR,
  50              ];
  51              $tmpDir = sys_get_temp_dir();
  52              $lastError = 'unknown reason';
  53              set_error_handler(function ($type, $msg) use (&$lastError) { $lastError = $msg; });
  54              for ($i = 0;; ++$i) {
  55                  foreach ($pipes as $pipe => $name) {
  56                      $file = sprintf('%s\\sf_proc_%02X.%s', $tmpDir, $i, $name);
  57  
  58                      if (!$h = fopen($file.'.lock', 'w')) {
  59                          if (file_exists($file.'.lock')) {
  60                              continue 2;
  61                          }
  62                          restore_error_handler();
  63                          throw new RuntimeException('A temporary file could not be opened to write the process output: '.$lastError);
  64                      }
  65                      if (!flock($h, \LOCK_EX | \LOCK_NB)) {
  66                          continue 2;
  67                      }
  68                      if (isset($this->lockHandles[$pipe])) {
  69                          flock($this->lockHandles[$pipe], \LOCK_UN);
  70                          fclose($this->lockHandles[$pipe]);
  71                      }
  72                      $this->lockHandles[$pipe] = $h;
  73  
  74                      if (!fclose(fopen($file, 'w')) || !$h = fopen($file, 'r')) {
  75                          flock($this->lockHandles[$pipe], \LOCK_UN);
  76                          fclose($this->lockHandles[$pipe]);
  77                          unset($this->lockHandles[$pipe]);
  78                          continue 2;
  79                      }
  80                      $this->fileHandles[$pipe] = $h;
  81                      $this->files[$pipe] = $file;
  82                  }
  83                  break;
  84              }
  85              restore_error_handler();
  86          }
  87  
  88          parent::__construct($input);
  89      }
  90  
  91      public function __destruct()
  92      {
  93          $this->close();
  94      }
  95  
  96      /**
  97       * {@inheritdoc}
  98       */
  99      public function getDescriptors()
 100      {
 101          if (!$this->haveReadSupport) {
 102              $nullstream = fopen('NUL', 'c');
 103  
 104              return [
 105                  ['pipe', 'r'],
 106                  $nullstream,
 107                  $nullstream,
 108              ];
 109          }
 110  
 111          // We're not using pipe on Windows platform as it hangs (https://bugs.php.net/51800)
 112          // We're not using file handles as it can produce corrupted output https://bugs.php.net/65650
 113          // So we redirect output within the commandline and pass the nul device to the process
 114          return [
 115              ['pipe', 'r'],
 116              ['file', 'NUL', 'w'],
 117              ['file', 'NUL', 'w'],
 118          ];
 119      }
 120  
 121      /**
 122       * {@inheritdoc}
 123       */
 124      public function getFiles()
 125      {
 126          return $this->files;
 127      }
 128  
 129      /**
 130       * {@inheritdoc}
 131       */
 132      public function readAndWrite($blocking, $close = false)
 133      {
 134          $this->unblock();
 135          $w = $this->write();
 136          $read = $r = $e = [];
 137  
 138          if ($blocking) {
 139              if ($w) {
 140                  @stream_select($r, $w, $e, 0, Process::TIMEOUT_PRECISION * 1E6);
 141              } elseif ($this->fileHandles) {
 142                  usleep(Process::TIMEOUT_PRECISION * 1E6);
 143              }
 144          }
 145          foreach ($this->fileHandles as $type => $fileHandle) {
 146              $data = stream_get_contents($fileHandle, -1, $this->readBytes[$type]);
 147  
 148              if (isset($data[0])) {
 149                  $this->readBytes[$type] += \strlen($data);
 150                  $read[$type] = $data;
 151              }
 152              if ($close) {
 153                  ftruncate($fileHandle, 0);
 154                  fclose($fileHandle);
 155                  flock($this->lockHandles[$type], \LOCK_UN);
 156                  fclose($this->lockHandles[$type]);
 157                  unset($this->fileHandles[$type], $this->lockHandles[$type]);
 158              }
 159          }
 160  
 161          return $read;
 162      }
 163  
 164      /**
 165       * {@inheritdoc}
 166       */
 167      public function haveReadSupport()
 168      {
 169          return $this->haveReadSupport;
 170      }
 171  
 172      /**
 173       * {@inheritdoc}
 174       */
 175      public function areOpen()
 176      {
 177          return $this->pipes && $this->fileHandles;
 178      }
 179  
 180      /**
 181       * {@inheritdoc}
 182       */
 183      public function close()
 184      {
 185          parent::close();
 186          foreach ($this->fileHandles as $type => $handle) {
 187              ftruncate($handle, 0);
 188              fclose($handle);
 189              flock($this->lockHandles[$type], \LOCK_UN);
 190              fclose($this->lockHandles[$type]);
 191          }
 192          $this->fileHandles = $this->lockHandles = [];
 193      }
 194  }


Generated: Mon Nov 25 19:05:08 2024 Cross-referenced by PHPXref 0.7.1