Get the data from the multi handle
protected function perform() {
  // @codeCoverageIgnoreStart
  // Weird things can happen when making HTTP requests in __destruct methods
  if (!$this->multiHandle) {
    return;
  }
  // @codeCoverageIgnoreEnd
  // If there are no requests to send, then exit from the function
  if ($this->scope <= 0) {
    if ($this
      ->count() == 0) {
      return;
    }
  }
  elseif (empty($this->requests[$this->scope])) {
    return;
  }
  // Create the polling event external to the loop
  $event = array(
    'curl_multi' => $this,
  );
  while (1) {
    $active = $this
      ->executeHandles();
    // Get messages from curl handles
    while ($done = curl_multi_info_read($this->multiHandle)) {
      $request = $this->resourceHash[(int) $done['handle']];
      $handle = $this->handles[$request];
      try {
        $this
          ->processResponse($request, $handle, $done);
      } catch (\Exception $e) {
        $this
          ->removeErroredRequest($request, $e);
      }
    }
    // Notify each request as polling and handled queued responses
    $scopedPolling = $this->scope <= 0 ? $this
      ->all() : $this->requests[$this->scope];
    // Exit the function if there are no more requests to send
    if (empty($scopedPolling)) {
      break;
    }
    // Notify all requests that requests are being polled
    foreach ($scopedPolling as $request) {
      $event['request'] = $request;
      $request
        ->dispatch(self::POLLING_REQUEST, $event);
    }
    if ($active) {
      // Select the curl handles until there is any activity on any of the open file descriptors
      // See https://github.com/php/php-src/blob/master/ext/curl/multi.c#L170
      $active = $this
        ->executeHandles(true, 0.1);
    }
    else {
      // Sleep to prevent eating CPU because no requests are actually pending a select call
      usleep(500);
    }
  }
}