Hello Guido, On 10 août 2015, at 15:32, Guido van Rossum <gu...@python.org> wrote:
> Folks, can we stop the testy interaction? Oops — sorry about that. > I'm personally confused how a protocol can require any kind of exchange on > shutdown. Indeed, even if a protocol recommends an exchange on shutdown, it needs a fallback when that exchange doesn’t complete. In the case of WebSockets, there’s a concept of “normal closure” which involves a closing handshake: https://tools.ietf.org/html/rfc6455#section-7.3 <https://tools.ietf.org/html/rfc6455#section-7.3>. Everything else is an “abnormal closure”. TCP has a comparable closing handshake at a lower level (usually FIN / ACK+FIN / ACK). > Surely the clients can't rely on this exchange? Because it's always possible > that the server crashes (or a network partition appears) without having this > exchange. And if the process crashes, TCP should have enough of a handshake > to tell the remote end the socket has closed immediately -- there shouldn't > be any timeout involved here. So perhaps this requirement (if it is in the > spec) is just encouraging poorly written clients that will misbehave or hang > without this designated closing exchange? (Or is it a work-around for a known > browser issue?) Yes, it’s a work-around. The TCP connection termination may not be reliable in the presence of (poorly implemented) proxies: https://tools.ietf.org/html/rfc6455#section-1.4 <https://tools.ietf.org/html/rfc6455#section-1.4>. (Also, depending on the TCP open/close handshaking for the application protocol open/close handshaking may be considered a violation of the OSI model, but that's a rather theoretical and unconvincing argument.) > I do have to agree with others on the thread that doing something special for > all open client connections seems to be an application-level thing. Yes, I’m now convinced that it’s the way to go. Since I’m wrapping create_server(), it makes sense to wrap Server as well. The pattern that looked strange to me is just a symptom of the circular dependency: protocol factory => object that knows how to shut down the server => result of create_server => arguments of create_server, including the protocol factory => … I can break it in various ways and none of them is going to look much better than the others. On a related topic, is there a reason why Server.close() and Server.wait_closed() are distinct? It seems to me that most code will call close() and yield from wait_closed() in a row. (Underlying idea: if create_server() had simply returned a coroutine to close the server, I wouldn’t have been tempted to subclass Server. I’m not proposing changes, just making thought experiments.) > Also, how do you detect this server shutdown? Is it a signal? There’s nothing special, it’s just the place in the code where the server shuts down, probably because an administrator is stopping or restarting it. For example: loop = asyncio.get_event_loop() server = websockets.serve(handler, 'localhost', 8765) loop.run_until_complete(server) try: loop.run_forever() except KeyboardInterrupt: # == at this point the server should close active connections == server.close() loop.run_until_complete(server.wait_closed()) -- Aymeric.