Websocket clients can disconnect ungracefully, don't notify application #1388

andrewconner opened this Issue Jul 26, 2013 · 7 comments


None yet
5 participants

andrewconner commented Jul 26, 2013

When using a long-lived websocket connection, clients frequently are able to disconnect uncleanly. Typically this happens (on desktop and mobile) when they lose wifi signal, close their laptop lid, power off abruptly, etc.

Play doesn't seem to get any notification this has happened, so the server believes the client is still connected. Taken from the Play examples:

    def index = WebSocket.using[String] { request => 
      val in = Iteratee.foreach[String](println).mapDone { _ =>
      val out = Enumerator("Hello!")
      (in, out)

You'd expect that the mapDone would be called in all cases. However, in unclean disconnect cases, it's not called.

To reproduce, you'll likely need two computers (or virtual machines). Run Play! on one, and connect with the other. If you disconnect by closing the browser, leaving the page, etc, everything works as expected. Reconnect, then cause the client to abruptly disconnect (kill -9 does not work here) — my favorite is using a virtual machine and simulating pulling the power.

"Disconnected" never hits the console. This is more than a bookkeeping issue, because it can cause resources to be left open, and for the server to try to push things down the socket.

I realize that much of this may be hitting limits of netty. However, what are our options here? Our current solution is an application-level ping, with a cleanup actor. Works alright for websockets, but not so well for something like a chunked response.


jroper commented Aug 2, 2013

It's not so much hitting the limits of netty, as it is hitting the limits of computer networking in general. If a host suddenly disappears, there's no way for the other end to know that, since if it's disappeared, it can't tell the other end that it just disappeared.

One thing that Play doesn't provide that we could provide is the ability to turn on TCP keepAlive for the sockets it uses. This causes a TCP keepalive packet to be sent every so often, how often that is depends on the OS, it usually defaults to 2 hours, and configuring it usually affects the whole system, not just the application you're running. This may or may not be what you want.

Another thing that we do plan on providing in the future is the ability to configure read and idle timeouts on sockets. This would mean just closing the connection if there was no activity for a given period, regardless of whether it was still good. This may or may not be what you want.

The only other solution is what you're currently doing, sending your own ping.


andrewconner commented Aug 2, 2013

Thanks. Read and idle timeouts would actually work great. Our app is fairly chatty, so several minutes without a message almost always means a dead or inactive client.

@jroper jroper closed this Oct 16, 2013


andrewconner commented Oct 16, 2013

@jroper Is there any plan for built-in read and idle timeouts on websockets?


jroper commented Oct 16, 2013

There are open tickets for read/idle timeouts, these would apply to both WebSockets and ordinary requests.

Also, with the move to akka-http (spray), we'll get this for free.

david04 commented Nov 18, 2015

Is this now available in the latest Play versions? (the read and idle timeouts on websockets)

Is this something available with Play2.5?

@TheChifer TheChifer referenced this issue in fdimuccio/play2-sockjs Mar 21, 2016


Detect ungraceful client disconnects #18


pauldraper commented May 1, 2016

There are open tickets for read/idle timeouts, these would apply to both WebSockets and ordinary requests.

@jroper, I cannot find these issues https://github.com/playframework/playframework/issues?utf8=%E2%9C%93&q=is%3Aissue+idle

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment