[prev in list] [next in list] [prev in thread] [next in thread] 

List:       tomcat-user
Subject:    Re: Intercepting WebSocket ping messages
From:       Mark Thomas <markt () apache ! org>
Date:       2017-03-31 15:25:19
Message-ID: cb6c303a-78f6-340a-724a-490c6e9c2cc0 () apache ! org
[Download RAW message or body]

On 31/03/17 15:03, Robert Lewis wrote:
> We have a Server <-> Client connection. The client periodically sends pings
> to the server, and Tomcat will respond with a sendPong() on a container
> thread, but the same instance of WsRemoteEndpointImplServer we are actively
> sending writes on. WsRemoteEndpointImplServer.doWrite() does not seem
> thread safe, so I have a feeling that tomcat handling the pongs on a
> separate thread is interfering with our constant calls to doWrite() on the
> same instance of WsRemoteEndpointImplServer.
> 
> If I could synchronize the pong with our application application calls to
> sendBinary(), I could fix a potential problem. If it is not supported,
> completely understand. I apologize as I have yet to time this perfectly
> where the calls do overlap. Do you happen to know if these calls will be
> synchronized by the container?

Yes, Tomcat should handle this for you.

> I attached logging into WsRemoteEndpointImplServer (for doWrite() and
> onWritePossible()), this includes start and end of the function calls, and
> each start will show a hashcode of the WsRemoteEndpointImplServer instance,
> and a hashcode of the SendHandler instance (endpointhash:handlerhash),
> where two threads are making what seems not so thread safe calls.

"seems"? Can you be more precise. To be clear, if you can show exactly
what the problem is / how the thread-safety problem occurs then you
stand a much greater chance of it being fixed.

Mark


> The first
> thread is the application calling down to doWrite() (locked at the
> application level) and the second thread is a container thread responding
> to a ping:
> 
> Thread 1 (Application Synchronized)
> --------------------------------------------
> http-nio-8443-exec-5: doWrite (start) 909703826:81194941
> java.lang.Thread.getStackTrace(Thread.java:1556)
> 
> org.apache.tomcat.websocket.server.WsRemoteEndpointImplServer.doWrite(WsRemoteEndpointImplServer.java:81)
>  
> org.apache.tomcat.websocket.WsRemoteEndpointImplBase.writeMessagePart(WsRemoteEndpointImplBase.java:453)
>  
> org.apache.tomcat.websocket.WsRemoteEndpointImplBase.startMessage(WsRemoteEndpointImplBase.java:341)
>  
> org.apache.tomcat.websocket.WsRemoteEndpointImplBase.startMessageBlock(WsRemoteEndpointImplBase.java:273)
>  
> org.apache.tomcat.websocket.WsRemoteEndpointImplBase.sendBytes(WsRemoteEndpointImplBase.java:134)
>  
> org.apache.tomcat.websocket.WsRemoteEndpointBasic.sendBinary(WsRemoteEndpointBasic.java:43)
>  
> com.thingworx.communications.server.connection.jsr356.Jsr356ServerConnection.sendBinaryMessage(Jsr356ServerConnection.java:613)
>  
> com.thingworx.communications.common.contexts.BaseContext.write(BaseContext.java:95)
> 
> com.thingworx.communications.common.messaging.ThingworxMessage.writeContent(ThingworxMessage.java:39)
>  
> com.thingworx.communications.server.modules.ServerCommunicationModuleBase.registerServerConnection(ServerCommunicationModuleBase.java:141)
>  
> com.thingworx.communications.server.connection.jsr356.Jsr356ServerConnection.registerConnection(Jsr356ServerConnection.java:332)
>  
> com.thingworx.communications.server.connection.jsr356.Jsr356ServerConnection.onMessage(Jsr356ServerConnection.java:304)
>  sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> 
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
> 
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
>  java.lang.reflect.Method.invoke(Method.java:498)
> 
> org.apache.tomcat.websocket.pojo.PojoMessageHandlerWholeBase.onMessage(PojoMessageHandlerWholeBase.java:80)
>  
> org.apache.tomcat.websocket.WsFrameBase.sendMessageBinary(WsFrameBase.java:592)
> 
> org.apache.tomcat.websocket.WsFrameBase.processDataBinary(WsFrameBase.java:549)
> org.apache.tomcat.websocket.WsFrameBase.processData(WsFrameBase.java:301)
> 
> org.apache.tomcat.websocket.WsFrameBase.processInputBuffer(WsFrameBase.java:131)
> 
> org.apache.tomcat.websocket.server.WsFrameServer.onDataAvailable(WsFrameServer.java:71)
>  
> org.apache.tomcat.websocket.server.WsHttpUpgradeHandler$WsReadListener.onDataAvailable(WsHttpUpgradeHandler.java:185)
>  
> org.apache.coyote.http11.upgrade.AbstractServletInputStream.onDataAvailable(AbstractServletInputStream.java:198)
>  
> org.apache.coyote.http11.upgrade.AbstractProcessor.upgradeDispatch(AbstractProcessor.java:96)
>  
> org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:664)
>  
> org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1520)
> 
> org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1476)
> 
> java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
> 
> java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
> 
> org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
> java.lang.Thread.run(Thread.java:745)
> http-nio-8443-exec-5: onWritePossible (start) 909703826:81194941
> java.lang.Thread.getStackTrace(Thread.java:1556)
> 
> org.apache.tomcat.websocket.server.WsRemoteEndpointImplServer.onWritePossible(WsRemoteEndpointImplServer.java:97)
>  
> org.apache.tomcat.websocket.server.WsRemoteEndpointImplServer.doWrite(WsRemoteEndpointImplServer.java:89)
>  
> org.apache.tomcat.websocket.WsRemoteEndpointImplBase.writeMessagePart(WsRemoteEndpointImplBase.java:453)
>  
> org.apache.tomcat.websocket.WsRemoteEndpointImplBase.startMessage(WsRemoteEndpointImplBase.java:341)
>  
> org.apache.tomcat.websocket.WsRemoteEndpointImplBase.startMessageBlock(WsRemoteEndpointImplBase.java:273)
>  
> org.apache.tomcat.websocket.WsRemoteEndpointImplBase.sendBytes(WsRemoteEndpointImplBase.java:134)
>  
> org.apache.tomcat.websocket.WsRemoteEndpointBasic.sendBinary(WsRemoteEndpointBasic.java:43)
>  
> com.thingworx.communications.server.connection.jsr356.Jsr356ServerConnection.sendBinaryMessage(Jsr356ServerConnection.java:613)
>  
> com.thingworx.communications.common.contexts.BaseContext.write(BaseContext.java:95)
> 
> com.thingworx.communications.common.messaging.ThingworxMessage.writeContent(ThingworxMessage.java:39)
>  
> com.thingworx.communications.server.modules.ServerCommunicationModuleBase.registerServerConnection(ServerCommunicationModuleBase.java:141)
>  
> com.thingworx.communications.server.connection.jsr356.Jsr356ServerConnection.registerConnection(Jsr356ServerConnection.java:332)
>  
> com.thingworx.communications.server.connection.jsr356.Jsr356ServerConnection.onMessage(Jsr356ServerConnection.java:304)
>  sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> 
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
> 
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
>  java.lang.reflect.Method.invoke(Method.java:498)
> 
> org.apache.tomcat.websocket.pojo.PojoMessageHandlerWholeBase.onMessage(PojoMessageHandlerWholeBase.java:80)
>  
> org.apache.tomcat.websocket.WsFrameBase.sendMessageBinary(WsFrameBase.java:592)
> 
> org.apache.tomcat.websocket.WsFrameBase.processDataBinary(WsFrameBase.java:549)
> org.apache.tomcat.websocket.WsFrameBase.processData(WsFrameBase.java:301)
> 
> org.apache.tomcat.websocket.WsFrameBase.processInputBuffer(WsFrameBase.java:131)
> 
> org.apache.tomcat.websocket.server.WsFrameServer.onDataAvailable(WsFrameServer.java:71)
>  
> org.apache.tomcat.websocket.server.WsHttpUpgradeHandler$WsReadListener.onDataAvailable(WsHttpUpgradeHandler.java:185)
>  
> org.apache.coyote.http11.upgrade.AbstractServletInputStream.onDataAvailable(AbstractServletInputStream.java:198)
>  
> org.apache.coyote.http11.upgrade.AbstractProcessor.upgradeDispatch(AbstractProcessor.java:96)
>  
> org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:664)
>  
> org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1520)
> 
> org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1476)
> 
> java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
> 
> java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
> 
> org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
> java.lang.Thread.run(Thread.java:745)
> http-nio-8443-exec-5: clearHandler (start) 909703826:81194941
> http-nio-8443-exec-5: clearHandler (end)
> http-nio-8443-exec-5: onWritePossible (end)
> http-nio-8443-exec-5: doWrite (end)
> 
> Thread 2 (Tomcat, Unsyncronized?)
> --------------------------------------------
> http-nio-8443-exec-10: doWrite (start) 909703826:1000491596
> java.lang.Thread.getStackTrace(Thread.java:1556)
> 
> org.apache.tomcat.websocket.server.WsRemoteEndpointImplServer.doWrite(WsRemoteEndpointImplServer.java:81)
>  
> org.apache.tomcat.websocket.WsRemoteEndpointImplBase.writeMessagePart(WsRemoteEndpointImplBase.java:453)
>  
> org.apache.tomcat.websocket.WsRemoteEndpointImplBase.startMessage(WsRemoteEndpointImplBase.java:341)
>  
> org.apache.tomcat.websocket.WsRemoteEndpointImplBase.startMessageBlock(WsRemoteEndpointImplBase.java:273)
>  
> org.apache.tomcat.websocket.WsRemoteEndpointImplBase.sendPong(WsRemoteEndpointImplBase.java:186)
>  
> org.apache.tomcat.websocket.WsRemoteEndpointBase.sendPong(WsRemoteEndpointBase.java:62)
>  
> org.apache.tomcat.websocket.WsFrameBase.processDataControl(WsFrameBase.java:351)
> org.apache.tomcat.websocket.WsFrameBase.processData(WsFrameBase.java:290)
> 
> org.apache.tomcat.websocket.WsFrameBase.processInputBuffer(WsFrameBase.java:131)
> 
> org.apache.tomcat.websocket.server.WsFrameServer.onDataAvailable(WsFrameServer.java:71)
>  
> org.apache.tomcat.websocket.server.WsHttpUpgradeHandler$WsReadListener.onDataAvailable(WsHttpUpgradeHandler.java:185)
>  
> org.apache.coyote.http11.upgrade.AbstractServletInputStream.onDataAvailable(AbstractServletInputStream.java:198)
>  
> org.apache.coyote.http11.upgrade.AbstractProcessor.upgradeDispatch(AbstractProcessor.java:96)
>  
> org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:664)
>  
> org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1520)
> 
> org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1476)
> 
> java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
> 
> java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
> 
> org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
> java.lang.Thread.run(Thread.java:745)
> http-nio-8443-exec-10: onWritePossible (start) 909703826:1000491596
> java.lang.Thread.getStackTrace(Thread.java:1556)
> 
> org.apache.tomcat.websocket.server.WsRemoteEndpointImplServer.onWritePossible(WsRemoteEndpointImplServer.java:97)
>  
> org.apache.tomcat.websocket.server.WsRemoteEndpointImplServer.doWrite(WsRemoteEndpointImplServer.java:89)
>  
> org.apache.tomcat.websocket.WsRemoteEndpointImplBase.writeMessagePart(WsRemoteEndpointImplBase.java:453)
>  
> org.apache.tomcat.websocket.WsRemoteEndpointImplBase.startMessage(WsRemoteEndpointImplBase.java:341)
>  
> org.apache.tomcat.websocket.WsRemoteEndpointImplBase.startMessageBlock(WsRemoteEndpointImplBase.java:273)
>  
> org.apache.tomcat.websocket.WsRemoteEndpointImplBase.sendPong(WsRemoteEndpointImplBase.java:186)
>  
> org.apache.tomcat.websocket.WsRemoteEndpointBase.sendPong(WsRemoteEndpointBase.java:62)
>  
> org.apache.tomcat.websocket.WsFrameBase.processDataControl(WsFrameBase.java:351)
> org.apache.tomcat.websocket.WsFrameBase.processData(WsFrameBase.java:290)
> 
> org.apache.tomcat.websocket.WsFrameBase.processInputBuffer(WsFrameBase.java:131)
> 
> org.apache.tomcat.websocket.server.WsFrameServer.onDataAvailable(WsFrameServer.java:71)
>  
> org.apache.tomcat.websocket.server.WsHttpUpgradeHandler$WsReadListener.onDataAvailable(WsHttpUpgradeHandler.java:185)
>  
> org.apache.coyote.http11.upgrade.AbstractServletInputStream.onDataAvailable(AbstractServletInputStream.java:198)
>  
> org.apache.coyote.http11.upgrade.AbstractProcessor.upgradeDispatch(AbstractProcessor.java:96)
>  
> org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:664)
>  
> org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1520)
> 
> org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1476)
> 
> java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
> 
> java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
> 
> org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
> java.lang.Thread.run(Thread.java:745)
> http-nio-8443-exec-10: clearHandler (start) 909703826:1000491596
> http-nio-8443-exec-10: clearHandler (end)
> http-nio-8443-exec-10: onWritePossible (end)
> http-nio-8443-exec-10: doWrite (end)
> 
> 
> On Fri, Mar 31, 2017 at 9:01 AM, Mark Thomas <markt@apache.org> wrote:
> 
> > On 30/03/17 21:13, Robert Lewis wrote:
> > > Is there a way to intercept a ping message to send a pong?
> > 
> > The API doesn't support this.
> > 
> > 
> > > I need to do this synchronize sends to the endpoint.
> > 
> > Could you clarify your requirement? Tomcat should handle pong messages
> > automatically for you (as required by the spec).
> > 
> > Mark
> > 
> > 
> > 
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
> > For additional commands, e-mail: users-help@tomcat.apache.org
> > 
> > 
> 


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic