Wednesday, 3 July 2019

aiogevent event loop "fails" to track greenlets

I recently stumbled onto problem of mixing up gevent and asyncio-based code, because some synchronous libraries work just fine when I monkey-patch them with gevent.monkey.patch_all(). I found the aiogevent library, which seems to help by implementing the PEP 3156, and replace asyncio event loop with other implementation of your choice (in this case it's gevent). Last significant commits to git repository I found was made 4 years ago. After fixing setup.py, I managed to successfully install it, but problem is that it doesn't passes all the test.

One of those tests is test_soon, which spawns greenlet that should do operation and stop the loop. This test hangs forever, because loop.stop() doesn't have any effect on the loop, which is expected to stop when all tasks are finished. I wrote two snippets to check if it happens with traditional coroutines, and another with greenlets via gevent.spawn.

import gevent
import aiogevent
import asyncio

asyncio.set_event_loop_policy(aiogevent.EventLoopPolicy())

loop = asyncio.get_event_loop()

async def func():
    print('bloop')
    loop.stop()

loop.create_task(func())
loop.run_forever() # works alright and stops as soon as func finish

And with gevent.spawn:

import gevent
import aiogevent
import asyncio

asyncio.set_event_loop_policy(aiogevent.EventLoopPolicy())

loop = asyncio.get_event_loop()

def func():
    print('bloop')
    loop.stop()

g = gevent.spawn(func)
loop.run_forever() # func is executed as soon as loop runs, but loop.stop() is ignored

And the question: what could possibly go wrong here? I clearly see that greenlet runs after I start the loop, but it is "untracked" by the loop? I can't find the exact line in asyncio sources which corresponds to this mechanism, and the same for gevent - I'm not quite familliar with internals of those modules and searching through them is confusing, but I want to know what is difference and what changes to aiogevent's event loop must be done in order to pass the tests.



from aiogevent event loop "fails" to track greenlets

No comments:

Post a Comment