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 <ma...@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-unsubscr...@tomcat.apache.org >> For additional commands, e-mail: users-h...@tomcat.apache.org >> >> > --------------------------------------------------------------------- To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org