Skip to content

Commit a1ec745

Browse files
authored
Fix #561 pkasyncio.create_task keep ref to avoid GC bug (#562)
1 parent cb4323d commit a1ec745

2 files changed

Lines changed: 16 additions & 3 deletions

File tree

pykern/api/server.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,8 @@ def handle_on_close(self):
184184
self.destroy()
185185

186186
async def handle_on_message(self, msg):
187+
if self._destroyed:
188+
return
187189
m = None
188190
try:
189191
m = _ServerMsg(self)
@@ -232,8 +234,8 @@ async def get(self, *args, **kwargs):
232234

233235
async def on_message(self, msg):
234236
try:
235-
# WebSocketHandler only allows one on_message at a time.
236-
asyncio.create_task(self.pykern_connection.handle_on_message(msg))
237+
# WebSocketHandler only allows one on_message at a time
238+
pykern.pkasyncio.create_task(self.pykern_connection.handle_on_message(msg))
237239
except Exception as e:
238240
pkdlog("exception={} stack={}", e, pkdexc())
239241

pykern/pkasyncio.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
_cfg = None
2020

21+
_background_tasks = set()
22+
2123

2224
class Loop:
2325
def __init__(self):
@@ -134,7 +136,16 @@ def cfg_port(value):
134136

135137

136138
def create_task(coro):
137-
return asyncio.create_task(coro)
139+
"""Create a task
140+
141+
Keeps a global reference to the task so to avoid the garbage
142+
collector running before the task is run.
143+
https://docs.python.org/3/library/asyncio-task.html#asyncio.create_task
144+
"""
145+
t = asyncio.create_task(coro)
146+
_background_tasks.add(t)
147+
t.add_done_callback(_background_tasks.discard)
148+
return t
138149

139150

140151
async def sleep(secs):

0 commit comments

Comments
 (0)