self._fds: dict[int, int] = {}
self._timeout: object | None = None
- # libcurl has bugs that sometimes cause it to not report all
- # relevant file descriptors and timeouts to TIMERFUNCTION/
- # SOCKETFUNCTION. Mitigate the effects of such bugs by
- # forcing a periodic scan of all active requests.
- self._force_timeout_callback = ioloop.PeriodicCallback(
- self._handle_force_timeout, 1000
- )
- self._force_timeout_callback.start()
-
# Work around a bug in libcurl 7.29.0: Some fields in the curl
# multi object are initialized lazily, and its destructor will
# segfault if it is destroyed without having been used. Add
self._multi.remove_handle(dummy_curl_handle)
def close(self) -> None:
- self._force_timeout_callback.stop()
if self._timeout is not None:
self.io_loop.remove_timeout(self._timeout)
for curl in self._curls:
# Set below properties to None to reduce the reference count of current
# instance, because those properties hold some methods of current
# instance that will case circular reference.
- self._force_timeout_callback = None # type: ignore
self._multi = None
def fetch_impl(
if new_timeout >= 0:
self._set_timeout(new_timeout)
- def _handle_force_timeout(self) -> None:
- """Called by IOLoop periodically to ask libcurl to process any
- events it may have forgotten about.
- """
- while True:
- try:
- ret, num_handles = self._multi.socket_all()
- except pycurl.error as e:
- ret = e.args[0]
- if ret != pycurl.E_CALL_MULTI_PERFORM:
- break
- self._finish_pending_requests()
-
def _finish_pending_requests(self) -> None:
"""Process any requests that were completed by the last
call to multi.socket_action.