voyent
HashMap concurrent access leads to corruption of the map and eventual deadlock  XML
Forum Index -> Components
Author Message
garr0171


Joined: 30/Apr/2011 12:43:31
Messages: 10
Offline



In one of our applications using icefaces we are getting random deadlocks in production. The cause of the deadlocks seem to be the corruption of a HashMap in the com.icesoft.faces.component.panelseries.UISeries class caused by concurrent requests.

I developed a selenium test that was able to replicate the error. The basic steps are the following
1. From the main application page click a button that opens a pop-up window
2. Click a button in the pop-up window that loads a bunch of data
2.1. The structure of the page may be at fault. It is a table having collapsible panels as rows, the body of the collapsible panel is a panel series of more collapsible panels that finally have a table for their body.
3. Wait for a random number of milliseconds (narrowed down once I found an approximate amount of time to wait for my machine)
4. Close the window at about the same time the data is loaded

I believe what is happening is the following
1. UISeries children are saved in the map during the request to fetch data
2. When the browser window is closed a dispose window request is handled by the WindowScopeManager, which, as part of the dispose window operation, initiates processing of the lifecycle, which will again interact with the saved children map in UISeries.

When the above operations happen concurrently the HashMap gets corrupted and never returns from a get. When this happens the entire application stops responding because requests get stuck waiting for the synchroized method WindowScopeManager.disposeWindow.

We're resolving this problem by adding synchronization for the HashMaps in UISeries.

Unfortunately I've been unable to recreate the problem with a dumbed down application (if I do I'll attach to the thread), but I just wanted to throw this out there in case others run across the same problem, and as a general question on whether non-thread safe maps should be used within the framework.

Configuration
Icefaces EE 2.0.0
Tomcat 6.0.32
All beans are Session, View, and Request scope (no window scope beans)

jstack snippet that leads to the conclusion of the HashMap being corrupted:
"tomcat-http--43" daemon prio=10 tid=0x00002aaabc94f000 nid=0x12e3 runnable [0x000000004372c000]
java.lang.Thread.State: RUNNABLE
at java.util.HashMap.get(HashMap.java:303)
at com.icesoft.faces.component.panelseries.UISeries.restoreChild(UISeries.java:535)
at com.icesoft.faces.component.panelseries.PanelSeries.restoreChild(PanelSeries.java:113)
at com.icesoft.faces.component.panelseries.UISeries.restoreChildState(UISeries.java:473)
at com.icesoft.faces.component.panelseries.UISeries.restoreChildState(UISeries.java:476)
at com.icesoft.faces.component.panelseries.UISeries.restoreChildState(UISeries.java:476)
at com.icesoft.faces.component.panelseries.UISeries.restoreChildrenState(UISeries.java:461)
at com.icesoft.faces.component.panelseries.UISeries.setRowIndex(UISeries.java:137)
at com.icesoft.faces.component.panelseries.UISeries.visitColumnsAndRows(UISeries.java:916)
at com.icesoft.faces.component.panelseries.UISeries.visitTree(UISeries.java:831)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1600)
at com.icesoft.faces.component.panelseries.UISeries.visitColumnsAndRows(UISeries.java:928)
at com.icesoft.faces.component.panelseries.UISeries.visitTree(UISeries.java:831)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1600)
at com.icesoft.faces.component.panelseries.UISeries.visitColumnsAndRows(UISeries.java:928)
at com.icesoft.faces.component.panelseries.UISeries.visitTree(UISeries.java:831)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1600)
at com.icesoft.faces.component.panelseries.UISeries.visitColumnsAndRows(UISeries.java:934)
at com.icesoft.faces.component.panelseries.UISeries.visitTree(UISeries.java:831)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1600)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1600)
at com.icesoft.faces.component.panelseries.UISeries.visitColumnsAndRows(UISeries.java:897)
at com.icesoft.faces.component.panelseries.UISeries.visitTree(UISeries.java:831)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1600)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1600)
at javax.faces.component.UIForm.visitTree(UIForm.java:344)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1600)
at javax.faces.component.UINamingContainer.visitTree(UINamingContainer.java:163)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1600)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1600)
at com.sun.faces.lifecycle.RestoreViewPhase.deliverPostRestoreStateEvent(RestoreViewPhase.java:272)
at com.sun.faces.lifecycle.RestoreViewPhase.execute(RestoreViewPhase.java:254)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
at com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:113)
at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
at org.icefaces.impl.application.WindowScopeManager.disposeViewScopeBeans(WindowScopeManager.java:284)
at org.icefaces.impl.application.WindowScopeManager.disposeWindow(WindowScopeManager.java:270)
- locked <0x000000070825c258> (a java.lang.Class for org.icefaces.impl.application.WindowScopeManager)
at org.icefaces.impl.application.WindowScopeManager.handleResourceRequest(WindowScopeManager.java:151)
at javax.faces.application.ResourceHandlerWrapper.handleResourceRequest(ResourceHandlerWrapper.java:125)
at javax.faces.application.ResourceHandlerWrapper.handleResourceRequest(ResourceHandlerWrapper.java:125)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:393)
...

Here is a sample of a blocked thread
"tomcat-http--4" daemon prio=10 tid=0x00002aaabc601800 nid=0x1272 waiting for monitor entry [0x0000000043018000]
java.lang.Thread.State: BLOCKED (on object monitor)
at org.icefaces.impl.application.WindowScopeManager.disposeWindow(WindowScopeManager.java:263)
- waiting to lock <0x000000070825c258> (a java.lang.Class for org.icefaces.impl.application.WindowScopeManager)
at org.icefaces.impl.application.WindowScopeManager.handleResourceRequest(WindowScopeManager.java:151)
at javax.faces.application.ResourceHandlerWrapper.handleResourceRequest(ResourceHandlerWrapper.java:125)
at javax.faces.application.ResourceHandlerWrapper.handleResourceRequest(ResourceHandlerWrapper.java:125)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:393)
...
ted.goddard

Joined: 26/Oct/2004 00:00:00
Messages: 874
Offline


If you have no WindowScope beans, your application should likely not be sending the disposeWindow message to the server:

boolean sendDisposeWindow = !EnvUtils.isLazyWindowScope(context) ||
(windowScope != null && EnvUtils.containsBeans(windowScope)) || (viewScope != null && EnvUtils.containsDisposedBeans(viewScope));

Which version of ICEfaces are you using?
[Email]
garr0171


Joined: 30/Apr/2011 12:43:31
Messages: 10
Offline


We're using icefaces ee 2.0.0.GA

At some point along the way I read that view scope beans also trigger the dispose window message. The page is question is using a view scope bean.

Admittedly we could probably change it to session scope bean so we don't go through the dispose window workflow.... but it seems like the concurrent access to a map is a bigger problem. For example, I suspect (though admittedly I haven't tested it) that I could corrupt the map by double clicking or refreshing the browser. Please correct me if I'm wrong.

PS Thanks for the quick response :)
ted.goddard

Joined: 26/Oct/2004 00:00:00
Messages: 874
Offline


In the current release, @ViewScope beans only trigger a dispose window message if they are annotated with @WindowDisposed. In the older version you are using, the test is not as specific.
[Email]
dellmerca

Joined: 13/Jul/2017 01:06:13
Messages: 1
Offline


What is deadlock in java?

A lock occurs when multiple processes try to access the same resource at the same time. A deadlock occurs when the waiting process is still holding on to another resource that the first needs before it can finish. A Java multithreaded program may suffer from the deadlock condition because the synchronized keyword causes the executing thread to block while waiting for the lock, or monitor , associated with the specified object. More on...deadlock in Java

Dell
 
Forum Index -> Components
Go to:   
Powered by JForum 2.1.7ice © JForum Team