-
Bug
-
Resolution: Won't Fix
-
Normal
-
None
-
6.5.4
-
None
-
ZK 6.5.4 EE OSGi
GlassFish 3.1.2.2 with 5 listener threads
Firefox 26
Servlet 3 Push
-
None
The error I'm going to describe is a little bit complicated (took me 3 days of debugging...), so I'll try to describe it as simple as possible.
I have a ZK 6.5.4 EE OSGi application. I open the application in two browser tabs sharing the same ZK session. The application uses Servlet 3 Push to send update messages to the browser. When I switch between the tabs and send some zkau events (e.g. onMouseOut, onMouseOver, ...) to the server, he suddenly answers a zkau request with error code "467 Incomplete Request". Afterwards I can work in the tab without problem. But when I switch back to the other tab, I again get a 467 response for a zkau request. Whenever I switch between the two tabs, in the new tab two zkcomet requests are send to the server. The first one returns with response code 200, the second one is pending.
As I found out, the reason for the zkau request responding with error code 467 is a request which is not recycled correctly and still contains information from the last execution. I further found out, that this request is the same request as the one used for the first zkcomet request which returns with code 200. So the problem is, that the zkcomet request returns to the browser but is not correctly recycled.
After further researching on the ZK Comet Servlet Push implementation, I reconstructed the following process (IDs are examples):
-> I start in tab A. Then I switch to tab B, than back to tab A
1. For the first zkcomet request a new response object is created with ID 15940. It is marked as suspended by setting com.sun.grizzly.tcp.Response.isSuspended = true.
2. The old response object with ID 16075 (from the last zkcomet request executed in this tab) is cleaned (at CometServerPush.processRequest -> cleanAsyncInfo)
-> Cleaning the old response object leads to setting the ThreadLocale variable SUSPENDED_IN_CURRENT_THREAD of com.sun.grizzly.tcp.SuspendResponseUtils to false for the current thread
-> Because of setting SUSPENDED_IN_CURRENT_THREAD to false, the com.sun.grizzly.tcp.Request object is recycled (but not the PwcCoyoteRequest object held by the request)
-> Also the com.sun.grizzly.tcp.Response object is recycled and isSuspended is set to false
-> The zkcomet request returns with code 200
-> A new zkcomet request is send to the server, as the old one has returned
3. For the second zkcomet request a new response object is created with ID 16134. It is marked as suspended by setting Response.isSuspended = true.
4. The old response object with ID 15940 (from the first zkcomet request) is cleaned. But the isSuspended value of this request is set to false, so SUSPENDED_IN_CURRENT_THREAD does not become reset.
-> Because SUSPENDED_IN_CURRENT_THREAD is still true, the Response is not send back to client and not recycled (and also not the Request).
-> If afterwards a zkau request uses the same thread as the first zkcomet request, the 467 response is send back to the client (the Request objects are bound to the threads)
-> Now I switch back to tab B and than again to tab A. A new zkcomet request is send to the server.
5. For the zkcomet request a new response object is created with ID XXXXX. It is marked as suspended by setting com.sun.grizzly.tcp.Response.isSuspended = true.
6. The old response object with ID 16134 (from the last zkcomet request executed in this tab) is cleaned
And so on...
In my opinion the problem is the cleaning of the last zkcomet response object, as it leads to setting SUSPENDED_IN_CURRENT_THREAD to false, which than leads to incomplete recycling of the Request object bound to the thread.
I see two possible solutions:
1. Clean the old response object without setting SUSPENDED_IN_CURRENT_THREAD to false.
2. Not only recycle com.sun.grizzly.tcp.Request but also PwcCoyoteRequest object.
- relates to
-
ZK-2169 CometServerPush.getStartScript() should include org.zkoss.zkex.ui.comet.smartconnection.disabled in ee version
- Closed