Connection is closed incorrectly
- 主要语言
- Python
- 星标
- 1.9k
- 派生
- 272
- PR 合并指标
- 30 天内没有已合并 PR
描述
python==3.8.6
uvloop==0.14.0
pytest==6.1.2
When connection is closed using `Connection.ensure_closed` in uvloop, aiomysql raises a warning about unclosed resource.
If warnings are turned to errors by pytest, this leads to test failure.
Consider the following example:
```python
# test_aiomysql.py
import asyncio
import aiomysql
import pymysql
import pytest
from aiomysql import Connection
import uvloop
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
@pytest.mark.asyncio
@pytest.mark.filterwarnings("error") # convert all warnings to errors
async def test_uvloop():
ctx = pymysql.connections.Connection._create_ssl_ctx( # type: ignore
None, {"on": True}
)
config = {'password': 'VerySecure', 'connect_timeout': 10, 'db': 'locodatum', 'ssl': ctx, 'host': 'localhost', 'port': 3307, 'user': 'incountry', 'charset': 'utf8mb4'}
conn: Connection = await aiomysql.connect(**config)
await conn.ensure_closed()
```
```
$ pipenv run pytest -k test_uvloop --setup-show
...
test_uvloop.py
SETUP F event_loop
test_uvloop.py::test_uvloop (fixtures used: event_loop).
TEARDOWN F event_loopE
=========================================================================== ERRORS ===========================================================================
______________________________________________________________ ERROR at teardown of test_uvloop ______________________________________________________________
request = >
@pytest.fixture
def event_loop(request):
"""Create an instance of the default event loop for each test case."""
loop = asyncio.get_event_loop_policy().new_event_loop()
yield loop
> loop.close()
../../../../.local/share/virtualenvs/env/lib/python3.8/site-packages/pytest_asyncio/plugin.py:210:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
uvloop/loop.pyx:1366: in uvloop.loop.Loop.close
???
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
> ???
E OSError: [Errno 16] Resource busy
uvloop/loop.pyx:583: OSError
------------------------------------------------------------------ Captured stderr teardown ------------------------------------------------------------------
Traceback (most recent call last):
File "uvloop/handles/handle.pyx", line 96, in uvloop.loop.UVHandle._warn_unclosed
ResourceWarning: unclosed resource
Exception ignored in: 'uvloop.loop.__uv_walk_close_all_handles_cb'
Traceback (most recent call last):
File "uvloop/handles/handle.pyx", line 96, in uvloop.loop.UVHandle._warn_unclosed
ResourceWarning: unclosed resource
------------------------------------------------------------------- Captured log teardown --------------------------------------------------------------------
ERROR asyncio:plugin.py:210 Fatal error on transport TCPTransport
protocol:
transport:
Traceback (most recent call last):
File "uvloop/sslproto.pyx", line 416, in uvloop.loop.SSLProtocol.eof_received
File "uvloop/sslproto.pyx", line 579, in uvloop.loop.SSLProtocol._do_shutdown
File "uvloop/sslproto.pyx", line 589, in uvloop.loop.SSLProtocol._on_shutdown_complete
File "uvloop/loop.pyx", line 1259, in uvloop.loop.Loop.call_soon
File "uvloop/loop.pyx", line 635, in uvloop.loop.Loop._call_soon
File "uvloop/loop.pyx", line 639, in uvloop.loop.Loop._call_soon_handle
File "uvloop/loop.pyx", line 668, in uvloop.loop.Loop._check_closed
RuntimeError: Event loop is closed
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "uvloop/handles/stream.pyx", line 769, in uvloop.loop.__uv_stream_on_read_common
File "uvloop/handles/stream.pyx", line 615, in uvloop.loop.UVStream._on_eof
File "uvloop/sslproto.pyx", line 419, in uvloop.loop.SSLProtocol.eof_received
File "uvloop/handles/basetransport.pyx", line 251, in uvloop.loop.UVBaseTransport.close
File "uvloop/handles/basetransport.pyx", line 32, in uvloop.loop.UVBaseTransport._schedule_call_connection_lost
File "uvloop/loop.pyx", line 639, in uvloop.loop.Loop._call_soon_handle
File "uvloop/loop.pyx", line 668, in uvloop.loop.Loop._check_closed
RuntimeError: Event loop is closed
================================================================== short test summary info ===================================================================
ERROR test_uvloop.py::test_uvloop - OSError: [Errno 16] Resource busy
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! stopping after 1 failures !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
================================================================= 1 passed, 1 error in 0.30s =================================================================
```
Possible solution here would be to close `self._writer` properly, as described in the [StreamWriter documentation](https://docs.python.org/3.8/library/asyncio-stream.html#asyncio.StreamWriter.close).
In `aiomysql.Connection._ensure_closed` before calling `self.close` this should be done:
```python
self._writer.close()
await self._writer.wait_closed()
```
贡献指南
评估
这个 Issue 还没有评估数据。