Skip to content

Instantly share code, notes, and snippets.

@vxgmichel
Last active November 13, 2019 15:20
Show Gist options
  • Save vxgmichel/cf7f7bc2356920f07bc1380e444cb509 to your computer and use it in GitHub Desktop.
Save vxgmichel/cf7f7bc2356920f07bc1380e444cb509 to your computer and use it in GitHub Desktop.
Demonstrate a potential deadlock with service nurseries
import trio
import pytest
from contextlib import asynccontextmanager
from service_nursery import run_service_nursery
@asynccontextmanager
async def run_deadlock_service():
class service:
pass
async def target():
try:
service.running = True
service.stopped = trio.Event()
await trio.sleep_forever()
finally:
with trio.CancelScope(shield=True):
print("Cleanup target")
service.running = False
await trio.sleep(.2)
service.stopped.set()
async with open_service_nursery() as nursery:
nursery.start_soon(target)
try:
yield service
finally:
with trio.CancelScope(shield=True):
print("Cleanup with target running")
await trio.sleep(.1)
assert service.running
print("Cancel and join target")
# Uncomment this line to fix the deadlock
# nursery.child_task_scopes.shield = False
nursery.cancel_scope.cancel()
await service.stopped.wait()
print("Cleanup with target stopped")
assert not service.running
await trio.sleep(.1)
@pytest.mark.trio
async def test_deadlock():
async with run_deadlock_service():
await trio.sleep(.1)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment