This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

Bug 186528 - Deadlock between Property Sheet and AWT-EventQueue
Summary: Deadlock between Property Sheet and AWT-EventQueue
Status: RESOLVED FIXED
Alias: None
Product: guibuilder
Classification: Unclassified
Component: Code (show other bugs)
Version: 6.x
Hardware: All All
: P2 normal (vote)
Assignee: issues@guibuilder
URL:
Keywords:
: 187245 188157 190856 (view as bug list)
Depends on:
Blocks:
 
Reported: 2010-05-21 20:17 UTC by Jan Stola
Modified: 2010-10-15 09:02 UTC (History)
3 users (show)

See Also:
Issue Type: DEFECT
Exception Reporter:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jan Stola 2010-05-21 20:17:59 UTC
Found one Java-level deadlock:
=============================
"Property Sheet":
  waiting to lock monitor 0x06037444 (object 0x29fd2370, a java.lang.Class),
  which is held by "AWT-EventQueue-1"
"AWT-EventQueue-1":
  waiting to lock monitor 0x0aec8edc (object 0x1b573438, a org.netbeans.modules.form.RADVisualFormContainer),
  which is held by "Property Sheet"

Java stack information for the threads listed above:
===================================================
"Property Sheet":
        at java.beans.Introspector.findExplicitBeanInfo(Introspector.java:423)
        - waiting to lock <0x29fd2370> (a java.lang.Class for java.beans.Introspector)
        at java.beans.Introspector.<init>(Introspector.java:374)
        at java.beans.Introspector.getBeanInfo(Introspector.java:168)
        at java.beans.Introspector.getBeanInfo(Introspector.java:229)
        at java.beans.Introspector.<init>(Introspector.java:383)
        at java.beans.Introspector.getBeanInfo(Introspector.java:168)
        at java.beans.Introspector.getBeanInfo(Introspector.java:229)
        at java.beans.Introspector.<init>(Introspector.java:383)
        at java.beans.Introspector.getBeanInfo(Introspector.java:168)
        at org.openide.util.Utilities.getBeanInfo(Utilities.java:426)
        at org.netbeans.modules.form.FormUtils.getBeanInfo(FormUtils.java:1771)
        at org.netbeans.modules.form.BindingDesignSupport.getBindingDescriptors(BindingDesignSupport.java:255)
        at org.netbeans.modules.form.BindingDesignSupport.getBindingDescriptors(BindingDesignSupport.java:189)
        at org.netbeans.modules.form.RADComponent.createBindingProperties(RADComponent.java:1373)
        - locked <0x1b573438> (a org.netbeans.modules.form.RADVisualFormContainer)
        at org.netbeans.modules.form.RADComponent.getBindingProperties(RADComponent.java:685)
        - locked <0x1b573438> (a org.netbeans.modules.form.RADVisualFormContainer)
        at org.netbeans.modules.form.RADComponent.getAllBindingProperties(RADComponent.java:675)
        at org.netbeans.modules.form.RADComponent.createPropertySets(RADComponent.java:1145)
        at org.netbeans.modules.form.RADVisualComponent.createPropertySets(RADVisualComponent.java:221)
        at org.netbeans.modules.form.RADComponent.getProperties(RADComponent.java:647)
        at org.netbeans.modules.form.RADComponentNode.getPropertySets(RADComponentNode.java:178)
        at org.openide.explorer.propertysheet.PropertySheet$2.run(PropertySheet.java:594)
        at org.openide.util.RequestProcessor$Task.run(RequestProcessor.java:1418)
        at org.openide.util.RequestProcessor$Processor.run(RequestProcessor.java:1957)
"AWT-EventQueue-1":
        at org.netbeans.modules.form.RADComponent.getKnownBindingProperties(RADComponent.java:699)
        - waiting to lock <0x1b573438> (a org.netbeans.modules.form.RADVisualFormContainer)
        at org.netbeans.modules.form.BindingDesignSupport.collectBindingDefs(BindingDesignSupport.java:866)
        at org.netbeans.modules.form.BindingDesignSupport.collectBindingDefs(BindingDesignSupport.java:857)
        at org.netbeans.modules.form.BindingDesignSupport.establishUpdatedBindings(BindingDesignSupport.java:808)
        at org.netbeans.modules.form.VisualReplicator.createClone(VisualReplicator.java:209)
        at org.netbeans.modules.form.VisualReplicator.updateContainerLayout(VisualReplicator.java:276)
        at org.netbeans.modules.form.VisualReplicator.updateAddedComponents(VisualReplicator.java:342)
        at org.netbeans.modules.form.FormDesigner$FormListener.run(FormDesigner.java:2414)
        at org.netbeans.modules.form.FormLAF$3.run(FormLAF.java:329)
        - locked <0x18eecdc0> (a javax.swing.MultiUIDefaults)
        - locked <0x29fd2370> (a java.lang.Class for java.beans.Introspector)
        at org.openide.util.Mutex.doEventAccess(Mutex.java:1361)
        at org.openide.util.Mutex.readAccess(Mutex.java:271)
        at org.netbeans.modules.form.FormLAF.executeWithLookAndFeel(FormLAF.java:312)
        at org.netbeans.modules.form.FormDesigner$FormListener.processEvents(FormDesigner.java:2339)
        at org.netbeans.modules.form.FormDesigner$FormListener.formChanged(FormDesigner.java:2305)
        at org.netbeans.modules.form.FormModel.fireEvents(FormModel.java:1296)
        at org.netbeans.modules.form.FormModel.fireEventBatch(FormModel.java:1269)
        at org.netbeans.modules.form.FormModel.firePendingEvents(FormModel.java:1232)
        at org.netbeans.modules.form.FormModel.access$000(FormModel.java:68)
        at org.netbeans.modules.form.FormModel$2.run(FormModel.java:1212)
        at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
        at java.awt.EventQueue.dispatchEvent(EventQueue.java:597)
        at org.netbeans.core.TimableEventQueue.dispatchEvent(TimableEventQueue.java:137)
        at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
        at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
        at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
        at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)

Found 1 deadlock.
Comment 1 Jan Stola 2010-05-24 14:08:13 UTC
This is another problem caused by recent threading model change in Property Sheet. We will have to introduce a clear locking model in GUI builder to be able to bear with that change. The following comment will summarize the current knowledge in this area.
Comment 2 Jan Stola 2010-05-24 14:09:59 UTC
LOCKS

UIDefaults lock
- lock used by the underlying collection (of UIDefaults)

Introspector lock
- lock used by Introspector when searching for (and instantiating) explicit BeanInfo of a class

form-specific locks
- any other lock used by GUI builder's code

USE-CASES

* classloading of 3rd party component
- some 3rd party components modify the content of UIDefaults
  in their static initializer, i.e., are grabbing UIDefaults lock

* BeanInfo loading of 3rd party component
- instantiation of explicit BeanInfo may result in classloading
  of other 3rd party classes
- instantiation of explicit BeanInfo is performed under
  Introspector lock
- classloading of other 3rd party classes may attempt to grab
  UIDefaults lock
=> if any thread wants to grab both Introspector and UIDefaults
  locks then the order must be 'Introspector lock' before
  'UIDefaults lock'

* WYSIWYG look and feel in GUI builder
- NetBeans IDE modifies UIDefaults to implement some UI tweaks
- GUI builder reverts these modifications temporarily
  during painting, instantiating etc. (to implement WYSIWYG support)
- GUI builder has to lock UIDefaults to avoid unwanted rollback
  of any (potential) additional modifications of UIDefaults
  (performed by other modules)
- the code invoked it this 'LAF block' can result in BeanInfo
  loading => GUI builder has to lock Introspector as well
  (and must lock it before UIDefaults according to the previous
  use-case)

* GUI builder synchronization
- some GUI builder's code must be synchronized because it can
  be invoked from several threads
- it is common that this code attempts to grab Introspector lock
- it may happen that this code results in some 3rd party
  class loading, i.e., may attempt to grab UIDefaults lock
- this code can be invoked inside or outside the 'LAF block'
  (mentioned in the previous use-case)
- if the code is invoked in 'LAF block' then Introspector
  and UIDefaults locks are already grabbed by the thread
=> if any other thread wants to grab any of these locks
  then the order must be 'form-specific lock' after
  'Introspector lock' and/or 'UIDefaults lock'

SUMMARY

If there is any chance that some thread will attempt
to grab several of the following locks then they must
be grabbed in the following order:

'Introspector lock' before 'UIDefaults lock' before 'form-specific lock'
Comment 3 Jan Stola 2010-05-24 14:51:30 UTC
Fixed - getPropertySets() is called with both Introspector and UIDefaults locks grabbed.

Modified files: http://hg.netbeans.org/cdev/rev/a8913ce1eabc
Comment 4 Jan Stola 2010-06-07 08:01:49 UTC
*** Bug 187245 has been marked as a duplicate of this bug. ***
Comment 5 Jan Stola 2010-06-29 08:16:20 UTC
*** Bug 188157 has been marked as a duplicate of this bug. ***
Comment 6 Jan Stola 2010-10-15 09:02:38 UTC
*** Bug 190856 has been marked as a duplicate of this bug. ***