code: def _handle_timeout(self) -> None:
          
          self._timeout = None
          while True:
              try:
                  ret, num_handles = self._multi.socket_action(pycurl.SOCKET_TIMEOUT, 0)
              except pycurl.error as e:
                  ret = e.args[0]
              if ret != pycurl.E_CALL_MULTI_PERFORM:
                  break
          self._finish_pending_requests()
  
          # In theory, we shouldn't have to do this because curl will
          # call _set_timeout whenever the timeout changes.  However,
          # sometimes after _handle_timeout we will need to reschedule
          # immediately even though nothing has changed from curl's
          # perspective.  This is because when socket_action is
          # called with SOCKET_TIMEOUT, libcurl decides internally which
          # timeouts need to be processed by using a monotonic clock
          # (where available) while tornado uses python's time.time()
          # to decide when timeouts have occurred.  When those clocks
          # disagree on elapsed time (as they will whenever there is an
          # NTP adjustment), tornado might call _handle_timeout before
          # libcurl is ready.  After each timeout, resync the scheduled
          # timeout with libcurl's current state.
          new_timeout = self._multi.timeout()
          if new_timeout >= 0:
              self._set_timeout(new_timeout)
docs: Called by IOLoop when the requested timeout has passed.