Uploaded image for project: 'ZK'
  1. ZK
  2. ZK-4809

NPE with comet server push (servlet 3) reconnect on Tomcat

    XMLWordPrintable

Details

    Description

      Steps to Reproduce

      run the attached example using Tomcat

      place a breakpoint in org.zkoss.zkex.ui.comet.CometServerPush#activate (Line 514)

      click the buttons in the sequence:

      1. start long-op
      2. stop long-op (reaches the breakpoint)
      3. simulate comet re-connect
      4. continue the code from the breakpoint

      Current Result

      18:10:31.632 [ForkJoinPool.commonPool-worker-3] ERROR org.zkoss.zk.ui.impl.UiEngineImpl - 
      java.lang.NullPointerException: null
      	at org.apache.catalina.connector.Request.notifyAttributeRemoved(Request.java:1623)
      	at org.apache.catalina.connector.Request.removeAttribute(Request.java:1502)
      	at org.apache.catalina.connector.RequestFacade.removeAttribute(RequestFacade.java:552)
      	at org.zkoss.zk.ui.http.ExecutionImpl.removeAttribute(ExecutionImpl.java:503)
      	at LongOpComposer_12188.handleCustomEvent(LongOpComposer_12188.java:66)
      	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
      	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
      	at org.zkoss.zk.ui.select.Selectors$ComposerEventListener.onEvent(Selectors.java:673)
      	at org.zkoss.zk.ui.AbstractComponent.onEvent(AbstractComponent.java:3185)
      	at org.zkoss.zk.ui.AbstractComponent.service(AbstractComponent.java:3155)
      	at org.zkoss.zk.ui.AbstractComponent.service(AbstractComponent.java:3097)
      	at org.zkoss.zk.ui.impl.EventProcessor.process(EventProcessor.java:138)
      	at org.zkoss.zk.ui.impl.UiEngineImpl.processEvent(UiEngineImpl.java:1884)
      	at org.zkoss.zk.ui.impl.UiEngineImpl.process(UiEngineImpl.java:1656)
      	at org.zkoss.zk.ui.impl.UiEngineImpl.endUpdate(UiEngineImpl.java:1224)
      	at org.zkoss.zkex.ui.comet.CometServerPush.deactivate(CometServerPush.java:535)
      	at org.zkoss.zk.ui.impl.DesktopImpl.deactivateServerPush(DesktopImpl.java:1682)
      	at org.zkoss.zk.ui.Executions.deactivate(Executions.java:1011)
      	at LongOpComposer_12188.lambda$startLongOp$0(LongOpComposer_12188.java:52)
      	at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run$$$capture(CompletableFuture.java:1736)
      	at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java)
      	at java.base/java.util.concurrent.CompletableFuture$AsyncRun.exec(CompletableFuture.java:1728)
      	at java.base/java.util.concurrent.ForkJoinTask.doExec$$$capture(ForkJoinTask.java:290)
      	at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java)
      	at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020)
      	at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656)
      	at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594)
      	at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:183)
      

      Expected Result

      no exception

      Debug Information

      2 threads are accessing the CometServerpush._active attribute resulting in old Request objects stored in the current execution, when activating the serverpush

      The manual breakpoint makes the error happen 100% of the time (in a real situation that's a very rare race condition)

      cleanAsyncInfo is called from the re-connecting thread during
      org.zkoss.zkex.ui.comet.CometServerPush#processRequest (line 339)

      This method is trying to check for this.isActive() (line 434) to avoid clearing an activated request. However due to the breakpoint this will not detect the currently activated execution, and eventually call AsyncContext#complete and creating a new AsyncContext (with a new Request object)

      Once the breakpoint continues it will use an old Request object of the previous AsyncContext ... causing the exception.

      Workaround


      Attachments

        Issue Links

          Activity

            People

              rudyhuang rudyhuang
              cor3000 cor3000
              Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Time Tracking

                  Estimated:
                  Original Estimate - 2 days Original Estimate - 2 days
                  2d
                  Remaining:
                  Remaining Estimate - 0 minutes
                  0m
                  Logged:
                  Time Spent - 4 days
                  4d