How to safely close a connection in Trio?

217 views Asked by At

I have the application logic for a connection all wrapped in a big try/except/finally block:

async def serve(self, stream: trio.SocketStream):
    try:
        async with trio.open_nursery() as nursery:
            pass  # code goes here to do some reading and writing 

    except Exception as e:
        print("Got exception:", e)
    except trio.Cancelled:
        print("Cancelled")
        raise
    # some other handlers, mostly just logging

    finally:
        # ... some other stuff ...
        # ... then shut the connection:
        with trio.move_on_after(1):
            await stream.aclose()

I'm not clear whether I should try to close the connection in the finally clause. If the exception is due to an application error (invalid message from the connection, or coroutine cancelled) this seems like the right thing to do, but if the exception is that the connection was closed from the other end then this seems counter productive - I expect the old exception would get masked by a new one. Any thoughts? I could maybe wrap it in its own try/except and just ignore any exceptions.

1

There are 1 answers

0
Arthur Tacca On BEST ANSWER

On the python-trio/general Gitter chat, Joshua Oreman @oremanj kindly offered this answer:

Trio distinguishes between local and remote close. If a connection got closed by the remote side, it's still fine to aclose() it. (Precisely for this reason)

(If it got aclose()'d locally, it's also fine to aclose() it again. It's a noop (except for executing a checkpoint) in either case.)

You get ClosedResourceError if you use the connection after you closed it (this is a programming error that you should fix), as opposed to BrokenResourceError if you use the connection after some problem occurred on the other side (this should be expected sometimes due to the vagaries of networks).