python-trio / trio-asyncio

a re-implementation of the asyncio mainloop on top of Trio

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Problems with `create_task` and shielding

thearchitector opened this issue · comments

I'm trying to shim support into an existing third party tool by wrapping things with this package, in a similar way to what triopg does, but running into complications with asyncio.create_task and asyncio.shield.

The third party tool uses this pattern fairly often in order to shield cleanup tasks from cancellation:

task = asyncio.create_task(self.close())
await asyncio.shield(task)

The problem is that when my application hits those cleanups, I get the error:
TypeError: trio.run received unrecognized yield message.

Wrapping the shield in aio_as_trio causes an trio.TrioInternalError: internal error in Trio - please file a bug! error, and no other combination seems to work.

The problem goes away if I change the cleanup to:

with trio.CancelScope(shield=True):
  await self.close()

but unfortunately, there are some places where I cannot override classes and functions in order to replace the misbehaving code with the trio alternative.

I would guess the reasons for this may be because:

  1. trio-asyncio doesn't support Tasks, or
  2. the shielding logic is different and not possible to bridge, or both.

Is there anything that can be done about this?


edit: i suppose monkey patching may work? something egregious like this, but only for my specific case

import asyncio

async def _shield(coro):
    with trio.CancelScope(shield=True):
        return await coro

asyncio.create_task = lambda coro: coro
asyncio.shield = _shield

I shared exactly the same issue.

@thearchitector Sorry for the delay here. Can you please provide a complete and runnable example that reproduces the issue you're seeing?

@oremanj
sorry, took me a little bit to get around to this again, then some more to refamiliarize myself with what was going on.

with fresh eyes, i actually suspect that there isn't a bug here at all -- i was getting the error with a fairly complex shim, and after really reducing down all the func calls, it seems likely the problem is with nested aio_as_trio calls. as in, this does not work and produces the RuntimeError: Task got bad yield: WaitTaskRescheduled error (the "internal trio error" above was complexity-induced a red herring):

from trio_asyncio import aio_as_trio, run

async def callback():
    await aio_as_trio(asyncio.sleep(1))
    print("done")

async def asyncio_shield():
    task = asyncio.create_task(callback())
    await aio_as_trio(asyncio.shield(task))

run(asyncio_shield)

i dont expect that would have worked though, since the inner task is trio-flavored but the outer one is expecting it to be asyncio-flavored. so unless you say otherwise, and that behavior actually should be ok, this Issue is probably moot.

unless you say otherwise, and that behavior actually should be ok

Nope, that is not expected to work. Thus, let's mootify this issue (aka close it).