Skip to content

Asyncio tasks are not destroyed #16

Description

@belolap
  • GraphQL AioWS version: 0.2.0
  • Python version: Python 3.6.6 (default, Jun 27 2018, 14:44:17)
  • Operating System: Debian Stretch

Then I close ws connection to server after subscription some asyncio tasks are not destroyed. If I reload page of my webapp several times, there are a lot of existing tasks. It's possible memory leak.

Example app:

fromaiohttp.webimportApplication, run_app, WebSocketResponsefromgraphql_ws.aiohttpimportAiohttpSubscriptionServerfromgrapheneimportSchema, ObjectType, Field, ID# SchemaclassHistoryRecord(ObjectType):
id=ID()
classQuery(ObjectType):
history=Field(HistoryRecord)
defresolve_history(self, info):
returnHistoryRecord(id='first')
classSubscription(ObjectType):
history=Field(HistoryRecord)
defresolve_history(self, info):
asyncdefresolver(info):
yieldHistoryRecord(id='second')
returnresolver(info)
schema=Schema(query=Query, subscription=Subscription)
# ServerclassServer(AiohttpSubscriptionServer):
asyncdefon_open(self, *args, **kwargs):
print('Connection open')
awaitsuper().on_open(*args, **kwargs)
defon_close(self, *args, **kwargs):
print('Connection close')
super().on_close(*args, **kwargs)
subscription_server=Server(schema)
# WS handlerasyncdefsubscriptions(request):
ws=WebSocketResponse(protocols=('graphql-ws',))
awaitws.prepare(request)
awaitsubscription_server.handle(ws)
returnws# Applicationapp=Application()
app.router.add_get('/ws', subscriptions)
# List tasksfromasyncioimportTask, get_event_loop, sleepfromsysimportgetrefcountfromtimeimporttimeasyncdeftest():
count=0whileTrue:
awaitsleep(15)
count+=1print('. Timer iteration N', count)
tasks=Task.all_tasks()
print('.. Total tasks: %s'%len(tasks))
fortaskinsorted(tasks, key=lambdax: str(x)):
print('... refs={} {}'.format(getrefcount(task), task))
loop=get_event_loop()
loop.create_task(test())
# Fire!run_app(app, host='0.0.0.0', port=8888)

Task list after 3 connections. Full log attached.

Connection open
. Timer iteration N 6
.. Total tasks: 14
... refs=4 <Task finished coro=<AiohttpSubscriptionServer._handle() done, defined at /home/gik/src/graphql/graphql-ws/graphql_ws/aiohttp.py:54> result=None>
... refs=4 <Task finished coro=<AiohttpSubscriptionServer._handle() done, defined at /home/gik/src/graphql/graphql-ws/graphql_ws/aiohttp.py:54> result=None>
... refs=4 <Task finished coro=<AiohttpSubscriptionServer.on_connection_init() done, defined at /home/gik/src/graphql/graphql-ws/graphql_ws/aiohttp.py:93> result=None>
... refs=4 <Task finished coro=<AiohttpSubscriptionServer.on_connection_init() done, defined at /home/gik/src/graphql/graphql-ws/graphql_ws/aiohttp.py:93> result=None>
... refs=5 <Task finished coro=<AiohttpSubscriptionServer.on_connection_init() done, defined at /home/gik/src/graphql/graphql-ws/graphql_ws/aiohttp.py:93> result=None>
... refs=6 <Task finished coro=<AiohttpSubscriptionServer.on_start() done, defined at /home/gik/src/graphql/graphql-ws/graphql_ws/aiohttp.py:101> result=None>
... refs=4 <Task finished coro=<AiohttpSubscriptionServer.on_start() done, defined at /home/gik/src/graphql/graphql-ws/graphql_ws/aiohttp.py:101> result=None>
... refs=4 <Task finished coro=<AiohttpSubscriptionServer.on_start() done, defined at /home/gik/src/graphql/graphql-ws/graphql_ws/aiohttp.py:101> result=None>
... refs=6 <Task finished coro=<RequestHandler.start() done, defined at /usr/lib/python3/dist-packages/aiohttp/web_protocol.py:340> result=None>
... refs=5 <Task finished coro=<RequestHandler.start() done, defined at /usr/lib/python3/dist-packages/aiohttp/web_protocol.py:340> result=None>
... refs=4 <Task finished coro=<RequestHandler.start() done, defined at /usr/lib/python3/dist-packages/aiohttp/web_protocol.py:340> result=None>
... refs=5 <Task pending coro=<AiohttpSubscriptionServer._handle() running at /home/gik/src/graphql/graphql-ws/graphql_ws/aiohttp.py:62> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0x7fcec832af48>()]> cb=[shield.<locals>._done_callback() at /usr/lib/python3.6/asyncio/tasks.py:688]>
... refs=8 <Task pending coro=<RequestHandler.start() running at /usr/lib/python3/dist-packages/aiohttp/web_protocol.py:376> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at0x7fcec832ab58>()]>>
... refs=6 <Task pending coro=<test() running at ./bin/ex.py:63>>
Connection close

logfile.txt

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions