I created a hard to track down bug in our code, but do not understand why it occurs. The problem occurs when pushing the same async function multiple times to call soon. It does not happen with synchronous functions.
Here is a running example of the issue:
import asyncio
import sys
class TestObj(object):
def __init__(self):
self.test_data = {'a': 1, 'b': 2, 'c': 3}
self.loop = asyncio.get_event_loop()
self.loop.call_later(1, lambda: asyncio.ensure_future(self.calling_func()))
self.loop.call_later(2, self.calling_func_sync)
self.loop.call_later(4, sys.exit)
self.loop.run_forever()
async def do_something(self, k, v):
print("Values", k, v)
async def calling_func(self):
for k, v in self.test_data.items():
print("Sending", k, v)
self.loop.call_soon(lambda: asyncio.ensure_future(self.do_something(k, v)))
def do_something_sync(self, k, v):
print("Values_sync", k, v)
def calling_func_sync(self):
for k, v in self.test_data.items():
print("Sending_sync", k, v)
self.loop.call_soon(self.do_something_sync, k, v)
if __name__ == "__main__":
a = TestObj()
The output is:
Sending a 1
Sending b 2
Sending c 3
Values c 3
Values c 3
Values c 3
Sending_sync a 1
Sending_sync b 2
Sending_sync c 3
Values_sync a 1
Values_sync b 2
Values_sync c 3
Why is this happening and why? Only the asynchronous function is being stomped on. I would have expected that every call to call_soon pushes a new pointer onto the stack, but it seems there is a pointer to self.do_something that is getting overwritten.