Hi,
Note: (issue doesn't happens with blocking I/O, _only with
Http11NioProtocol_)
on some network, when Tomcat 7.0.50+ times a websocket connection, the
closeReason is set to 1006 but the websocket is not closed
automatically, as far as I can tell. So when an application try to
close, the following exception is thrown
java.io.IOException: Key must be cancelled
at
org.apache.coyote.http11.upgrade.UpgradeNioProcessor.writeToSocket(UpgradeNioProcessor.java:216)
at
org.apache.coyote.http11.upgrade.UpgradeNioProcessor.write(UpgradeNioProcessor.java:85)
at
org.apache.coyote.http11.upgrade.UpgradeOutbound.write(UpgradeOutbound.java:44)
at
org.apache.catalina.websocket.WsOutbound.doWriteBytes(WsOutbound.java:477)
at
org.apache.catalina.websocket.WsOutbound.doWriteText(WsOutbound.java:529)
at
org.apache.catalina.websocket.WsOutbound.doFlush(WsOutbound.java:267)
at org.apache.catalina.websocket.WsOutbound.close(WsOutbound.java:349)
at
org.atmosphere.container.version.TomcatWebSocket.close(TomcatWebSocket.java:100)
at
org.atmosphere.container.version.TomcatWebSocket.close(TomcatWebSocket.java:91)
at
org.atmosphere.cpr.AtmosphereResponse.close(AtmosphereResponse.java:842)
at
org.atmosphere.cpr.AtmosphereResourceImpl.cancel(AtmosphereResourceImpl.java:758)
at
org.atmosphere.cpr.AtmosphereResourceImpl.close(AtmosphereResourceImpl.java:834)
at
org.atmosphere.cpr.DefaultBroadcaster$4.run(DefaultBroadcaster.java:1126)
at
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:724)
If I don't call WsOutbound.close(), Tomcat will detect the broken
connection but will also fail with
java.io.IOException: Key must be cancelled
at
org.apache.coyote.http11.upgrade.UpgradeNioProcessor.writeToSocket(UpgradeNioProcessor.java:216)
at
org.apache.coyote.http11.upgrade.UpgradeNioProcessor.write(UpgradeNioProcessor.java:85)
at
org.apache.coyote.http11.upgrade.UpgradeOutbound.write(UpgradeOutbound.java:44)
at
org.apache.catalina.websocket.WsOutbound.doWriteBytes(WsOutbound.java:477)
at
org.apache.catalina.websocket.WsOutbound.doWriteText(WsOutbound.java:529)
at
org.apache.catalina.websocket.WsOutbound.writeTextMessage(WsOutbound.java:221)
at
org.atmosphere.container.version.TomcatWebSocket.write(TomcatWebSocket.java:57)
at org.atmosphere.websocket.WebSocket.write(WebSocket.java:222)
at org.atmosphere.websocket.WebSocket.write(WebSocket.java:187)
at org.atmosphere.websocket.WebSocket.write(WebSocket.java:42)
at
org.atmosphere.cpr.AtmosphereResponse$2.write(AtmosphereResponse.java:509)
at
org.atmosphere.handler.AbstractReflectorAtmosphereHandler.onStateChange(AbstractReflectorAtmosphereHandler.java:148)
at
org.atmosphere.config.managed.ManagedAtmosphereHandler.onStateChange(ManagedAtmosphereHandler.java:229)
at
org.atmosphere.cpr.DefaultBroadcaster.invokeOnStateChange(DefaultBroadcaster.java:1026)
at
org.atmosphere.cpr.DefaultBroadcaster.prepareInvokeOnStateChange(DefaultBroadcaster.java:1046)
at
org.atmosphere.cpr.DefaultBroadcaster.executeAsyncWrite(DefaultBroadcaster.java:887)
at
org.atmosphere.cpr.DefaultBroadcaster$3.run(DefaultBroadcaster.java:518)
at
java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
at java.util.concurrent.FutureTask.run(FutureTask.java:166)
at
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:724)
The problem is it seems under the hood the connection is still "alive"
and not closed properly, and it's impossible to close the dead websocket
properly.
As usual with those issues, it's pretty difficult to reproduce (I can't,
but one of my user is reproducing all the time).
Any idea how this can be fixed? I know it's the native/deprecated API,
but just in case it's a simple fix.
Thanks
-- Jeanfrancois