So I am starting my program like this:
try: b.loop.call_soon_threadsafe(b.loop.run_in_executor, None, lambda: trio.run(wallpaper))
except BaseException as e:
sys.exit(e)
try:
b.loop.run_until_complete(background_task())
except (KeyboardInterrupt,SystemExit,RuntimeError):
try: b.loop.close()
except BaseException: os._exit(0) # I have to do this or else the program will never close as asyncio will raise a RuntimeError indicating the loop is already closed. The `try` block might as well not exist cause it never works anyway.
The trio coroutine function starts like this:
sp = Sleeper()
async def wallpaper() -> typing.NoReturn:
with trio.CancelScope() as scope:
async with trio.open_nursery() as nursery:
nursery.start_soon(sp.sleep_handler)
await nursery.start(sp.watchdog)
await sp.nursery_closed()
scope.cancel()
and here is that class:
class Sleeper:
_end = trio.Event()
def __init__(this, *args, **kwds):
# some variables
@classmethod
def set_end(cls):
cls._end.set()
@classmethod
async def nursery_closed(cls):
await cls._end.wait()
@classmethod
def scope_canceled(cls):
return cls._end.is_set()
async def watchdog(this, task_status=trio.TASK_STATUS_IGNORED):
task_status.started()
while True:
await trio.sleep(5)
if b.is_closed(): # `b` is a class instance running in asyncio.
this.set_end()
break
"""# I can't use this outside of the main thread unfortunately, so I am trying the above instead.
with trio.open_signal_receiver(signal.SIGINT) as watcher:
task_status.started()
async for signum in watcher:
assert signum == signal.SIGINT
this.set_end()
"""
async def sleep_handler(this) -> typing.NoReturn:
if not this.scope_ready():
await this.nursery_spawned() # I didn't include it here but this is the same as below, but to indicate when it's ready rather than closed.
while not this.scope_canceled():
pass # stuff that is always running and never returning
I used to be able to end the program with b.loop.close
but with trio running, it could never execute and raised a RuntimeError which trapped my program into some infinite loop, not even stopping when I close the powershell window, requiring me to end the process from the task manager. That is solved with os_exit()
but it feels like I'm dodging the issue instead of correcting it. The asyncio portion of the code mostly can't be changed unless I greatly modify the library I'm using that runs with asyncio. Is there any big downside to just exiting with os._exit(0)
and is there a better way to run Trio alongside Asyncio? I want to keep using Trio.