lilydjwg / nvchecker

New version checker for software releases
MIT License
438 stars 70 forks source link

RuntimeError for httpx & aiohttp httpclient #215

Closed yan12125 closed 2 years ago

yan12125 commented 2 years ago

I'm investigating running nvchecker on Windows. The default pycurl httpclient requires libcurl and makes deployment harder, so I checked the pure-Python httpx httpclient and found some issues that are also reproducible on Arch Linux.

For httpx httpclient, there is an exception upon exit:

Exception ignored in atexit callback: <function cleanup at 0x7f8060e92ef0>
Traceback (most recent call last):
  File "/usr/lib/python3.10/site-packages/nvchecker/httpclient/httpx_httpclient.py", line 81, in cleanup
    loop = asyncio.get_event_loop()
  File "/usr/lib/python3.10/asyncio/events.py", line 656, in get_event_loop
    raise RuntimeError('There is no current event loop in thread %r.'
RuntimeError: There is no current event loop in thread 'MainThread'.

On GitHub Actions, the exception is different: (from https://github.com/lilydjwg/nvchecker/actions/runs/2080914454)

    return future.result()
  File "/home/runner/work/nvchecker/nvchecker/nvchecker/httpclient/httpx_httpclient.py", line 75, in aclose
    await client.aclose()
  File "/opt/hostedtoolcache/Python/3.10.2/x64/lib/python3.10/site-packages/httpx/_client.py", line 1946, in aclose
    await self._transport.aclose()
  File "/opt/hostedtoolcache/Python/3.10.2/x64/lib/python3.10/site-packages/httpx/_transports/default.py", line 365, in aclose
    await self._pool.aclose()
  File "/opt/hostedtoolcache/Python/3.10.2/x64/lib/python3.10/site-packages/httpcore/_async/connection_pool.py", line 307, in aclose
    await connection.aclose()
  File "/opt/hostedtoolcache/Python/3.10.2/x64/lib/python3.10/site-packages/httpcore/_async/connection.py", line 159, in aclose
    await self._connection.aclose()
  File "/opt/hostedtoolcache/Python/3.10.2/x64/lib/python3.10/site-packages/httpcore/_async/http2.py", line 310, in aclose
    await self._network_stream.aclose()
  File "/opt/hostedtoolcache/Python/3.10.2/x64/lib/python3.10/site-packages/httpcore/backends/asyncio.py", line 48, in aclose
    await self._stream.aclose()
  File "/opt/hostedtoolcache/Python/3.10.2/x64/lib/python3.10/site-packages/anyio/streams/tls.py", line 168, in aclose
    await self.transport_stream.aclose()
  File "/opt/hostedtoolcache/Python/3.10.2/x64/lib/python3.10/site-packages/anyio/_backends/_asyncio.py", line 1163, in aclose
    self._transport.close()
  File "/opt/hostedtoolcache/Python/3.10.2/x64/lib/python3.10/asyncio/selector_events.py", line 700, in close
    self._loop.call_soon(self._call_connection_lost, None)
  File "/opt/hostedtoolcache/Python/3.10.2/x64/lib/python3.10/asyncio/base_events.py", line 745, in call_soon
    self._check_closed()
  File "/opt/hostedtoolcache/Python/3.10.2/x64/lib/python3.10/asyncio/base_events.py", line 510, in _check_closed
Error:     raise RuntimeError('Event loop is closed')

aiohttp is also affected per GitHub Actions logs. Moreoever, aiohttp does not work locally for me:

[E 04-07 12:33:53.028 core:329] unbound: unexpected error happened error=RuntimeError('Timeout context manager should be used inside a task')
    Traceback (most recent call last):
      File "/usr/lib/python3.10/site-packages/nvchecker/util.py", line 262, in run_one
        version = await self.func(
      File "/usr/lib/python3.10/site-packages/nvchecker_source/github.py", line 25, in get_version
        return await get_version_real(name, conf, **kwargs)
      File "/usr/lib/python3.10/site-packages/nvchecker_source/github.py", line 114, in get_version_real
        data = await cache.get_json(url, headers = headers)
      File "/usr/lib/python3.10/site-packages/nvchecker/util.py", line 174, in get_json
        return await self.get(
      File "/usr/lib/python3.10/site-packages/nvchecker/util.py", line 201, in get
        r = await fu
      File "/usr/lib/python3.10/site-packages/nvchecker/util.py", line 162, in _get_json
        res = await session.get(url, headers=dict(headers))
      File "/usr/lib/python3.10/site-packages/nvchecker/httpclient/base.py", line 49, in get
        return await self.request(
      File "/usr/lib/python3.10/site-packages/nvchecker/httpclient/base.py", line 79, in request
        return await self.request_impl(
      File "/usr/lib/python3.10/site-packages/nvchecker/httpclient/aiohttp_httpclient.py", line 62, in request_impl
        res = await self.session.request(
      File "/usr/lib/python3.10/site-packages/aiohttp/client.py", line 466, in _request
        with timer:
      File "/usr/lib/python3.10/site-packages/aiohttp/helpers.py", line 701, in __enter__
        raise RuntimeError(
    RuntimeError: Timeout context manager should be used inside a task

asyncio-related codes may need non-trivial changes.

lilydjwg commented 2 years ago

It seems that we don't need to close the sessions now. I'll try a test to see if all versions are good.

lilydjwg commented 2 years ago

2e042d75764b0d97097ecdb68304e8b2db5c4303 looks good.

lilydjwg commented 2 years ago

There are some Unclosed connector warnings in the aiohttp tests run, but it doesn't show up with normal invocations. I'm going to leave it like that.

yan12125 commented 2 years ago

Thanks! I don't get Unclosed connector with aiohttp, either.