You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
this is because the trio implementation of BlockingPortal._spawn_task_from_thread uses trio.from_thread.run_sync. trio.from_thread.run_sync is not allowed to be called from trio threads because it can cause deadlocks1.
one way to fix this is by switching the trio implementation of BlockingPortal._spawn_task_from_thread from using trio.from_thread.run_sync(BlockingPortal._task_group.start_soon, ..., trio_token=...) to using TrioToken.run_sync_soon(BlockingPortal._task_group.start_soon, ...). the downside of this change is that it would change what happens if TaskGroup.start_soon fails:
with trio.from_thread.run_sync(BlockingPortal._task_group.start_soon, ..., trio_token=...), if TaskGroup.start_soon raises it gets propagated to the anyio.from_thread.run(_sync)? call site.
with TrioToken.run_sync_soon(BlockingPortal._task_group.start_soon, ...), if TaskGroup.start_soon raises it gets propagated up and crashes the portal's event loop.
that isn't ideal, so better options for fixing this, i think, are:
switch _trio.BlockingPortal._spawn_task_from_thread from using trio.from_thread.run_sync(BlockingPortal._task_group.start_soon, ..., trio_token=...) to using TrioToken.run_sync_soon(wrapper, ...), where wrapper is essentially just disable_ki_protection(AsyncioBackend.run_sync_from_thread.<locals>.wrapper).
this is more-or-less equivalent to writing a version of TrioBackend.run_sync_from_thread that has a relaxed deadlock heuristic.
will work no matter whether foo is called by (a) fully synchronous code (code with no event loop above) or by (b) synchronous code with an event loop above it.
(asyncio | trio).run(bar) would work as an alternative in case (a), of course. for case (b), an alternative to using a separate thread is greenback, but it has its own problems1.
reproducer: cd9deb1.
this is because the trio implementation of
BlockingPortal._spawn_task_from_thread
usestrio.from_thread.run_sync
.trio.from_thread.run_sync
is not allowed to be called from trio threads because it can cause deadlocks1.one way to fix this is by switching the trio implementation of
BlockingPortal._spawn_task_from_thread
from usingtrio.from_thread.run_sync(BlockingPortal._task_group.start_soon, ..., trio_token=...)
to usingTrioToken.run_sync_soon(BlockingPortal._task_group.start_soon, ...)
. the downside of this change is that it would change what happens ifTaskGroup.start_soon
fails:with
trio.from_thread.run_sync(BlockingPortal._task_group.start_soon, ..., trio_token=...)
, ifTaskGroup.start_soon
raises it gets propagated to theanyio.from_thread.run(_sync)?
call site.with
TrioToken.run_sync_soon(BlockingPortal._task_group.start_soon, ...)
, ifTaskGroup.start_soon
raises it gets propagated up and crashes the portal's event loop.that isn't ideal, so better options for fixing this, i think, are:
switch
_trio.BlockingPortal._spawn_task_from_thread
from usingtrio.from_thread.run_sync(BlockingPortal._task_group.start_soon, ..., trio_token=...)
to usingTrioToken.run_sync_soon(wrapper, ...)
, wherewrapper
is essentially justdisable_ki_protection(AsyncioBackend.run_sync_from_thread.<locals>.wrapper)
.this is more-or-less equivalent to writing a version of
TrioBackend.run_sync_from_thread
that has a relaxed deadlock heuristic.(in trio) relax the deadlock heuristic: see
from_thread.run(_sync)?
fails in any thread running Trio python-trio/trio#2534Footnotes
https://github.com/python-trio/trio/blob/4286063466aade470d531ddfb42664f07ae38583/trio/_threads.py#L248-L254 ↩
The text was updated successfully, but these errors were encountered: