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.

Reply via email to