Download
Getting Started
Members
Projects
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
More
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
Toggle navigation
Bugzilla – Attachment 146449 Details for
Bug 287096
[hotbug] ModelManagerImpl is highly susceptible to deadlock
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
Log In
[x]
|
Terms of Use
|
Copyright Agent
Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read
this important communication.
[patch]
Patch to use private condition lock, instead of load lock (3.1)
modelImpl.patch (text/plain), 11.67 KB, created by
Min Idzelis
on 2009-09-03 16:07:17 EDT
(
hide
)
Description:
Patch to use private condition lock, instead of load lock (3.1)
Filename:
MIME Type:
Creator:
Min Idzelis
Created:
2009-09-03 16:07:17 EDT
Size:
11.67 KB
patch
obsolete
>### Eclipse Workspace Patch 1.0 >#P org.eclipse.wst.sse.core >Index: src/org/eclipse/wst/sse/core/internal/SSECorePlugin.java >=================================================================== >RCS file: /cvsroot/webtools/sourceediting/plugins/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/SSECorePlugin.java,v >retrieving revision 1.17 >diff -u -r1.17 SSECorePlugin.java >--- src/org/eclipse/wst/sse/core/internal/SSECorePlugin.java 25 Feb 2009 22:44:04 -0000 1.17 >+++ src/org/eclipse/wst/sse/core/internal/SSECorePlugin.java 3 Sep 2009 20:08:35 -0000 >@@ -16,6 +16,7 @@ > import org.eclipse.core.runtime.Preferences; > import org.eclipse.wst.sse.core.StructuredModelManager; > import org.eclipse.wst.sse.core.internal.encoding.CommonEncodingPreferenceNames; >+import org.eclipse.wst.sse.core.internal.model.ModelManagerImpl; > import org.eclipse.wst.sse.core.internal.modelhandler.ModelHandlerRegistry; > import org.eclipse.wst.sse.core.internal.preferences.CommonModelPreferenceNames; > import org.eclipse.wst.sse.core.internal.provisional.IModelManager; >@@ -62,10 +63,13 @@ > public void stop(BundleContext context) throws Exception { > savePluginPreferences(); > >+ ((ModelManagerImpl) ModelManagerImpl.getInstance()).removePreferenceListener(); >+ > TaskScanningScheduler.shutdown(); > > FileBufferModelManager.shutdown(); > >+ > super.stop(context); > } > >Index: src/org/eclipse/wst/sse/core/internal/model/ModelManagerImpl.java >=================================================================== >RCS file: /cvsroot/webtools/sourceediting/plugins/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/model/ModelManagerImpl.java,v >retrieving revision 1.36 >diff -u -r1.36 ModelManagerImpl.java >--- src/org/eclipse/wst/sse/core/internal/model/ModelManagerImpl.java 22 Apr 2009 03:58:35 -0000 1.36 >+++ src/org/eclipse/wst/sse/core/internal/model/ModelManagerImpl.java 3 Sep 2009 20:08:35 -0000 >@@ -40,6 +40,7 @@ > import org.eclipse.core.runtime.IPath; > import org.eclipse.core.runtime.IStatus; > import org.eclipse.core.runtime.NullProgressMonitor; >+import org.eclipse.core.runtime.OperationCanceledException; > import org.eclipse.core.runtime.Path; > import org.eclipse.core.runtime.Platform; > import org.eclipse.core.runtime.QualifiedName; >@@ -47,9 +48,16 @@ > import org.eclipse.core.runtime.content.IContentDescription; > import org.eclipse.core.runtime.jobs.ILock; > import org.eclipse.core.runtime.jobs.Job; >+import org.eclipse.core.runtime.preferences.ConfigurationScope; >+import org.eclipse.core.runtime.preferences.IEclipsePreferences; >+import org.eclipse.core.runtime.preferences.IPreferencesService; >+import org.eclipse.core.runtime.preferences.IScopeContext; >+import org.eclipse.core.runtime.preferences.InstanceScope; >+import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent; > import org.eclipse.jface.text.BadLocationException; > import org.eclipse.jface.text.IDocument; > import org.eclipse.jface.text.IRegion; >+import org.eclipse.osgi.util.NLS; > import org.eclipse.text.edits.MultiTextEdit; > import org.eclipse.text.edits.ReplaceEdit; > import org.eclipse.text.edits.TextEdit; >@@ -96,6 +104,27 @@ > */ > public class ModelManagerImpl implements IModelManager { > >+ private static int WAIT_DELAY = getInt("org.eclipse.wst.sse.core.modelmanager.maxWaitDuringConcurrentLoad"); >+ private static boolean ALLOW_INTERRUPT_WAITING_THREAD = getBoolean("org.eclipse.wst.sse.core.modelmanager.allowInterruptsDuringConcurrentLoad"); >+ private static IEclipsePreferences.IPreferenceChangeListener LISTENER; >+ static { >+ InstanceScope scope = new InstanceScope(); >+ IEclipsePreferences instancePrefs = scope.getNode(SSECorePlugin.ID); >+ LISTENER = new IEclipsePreferences.IPreferenceChangeListener() { >+ >+ public void preferenceChange(PreferenceChangeEvent event) { >+ >+ if ("modelmanager.maxWaitDuringConcurrentLoad".equals(event.getKey())) { >+ WAIT_DELAY = getInt("org.eclipse.wst.sse.core.modelmanager.maxWaitDuringConcurrentLoad"); >+ } >+ else if ("modelmanager.allowInterruptsDuringConcurrentLoad".equals(event.getKey())) { >+ ALLOW_INTERRUPT_WAITING_THREAD = getBoolean("org.eclipse.wst.sse.core.modelmanager.allowInterruptsDuringConcurrentLoad"); >+ } >+ } >+ }; >+ instancePrefs.addPreferenceChangeListener(LISTENER); >+ } >+ > static class ReadEditType { > ReadEditType(String type) { > } >@@ -109,7 +138,8 @@ > int referenceCountForRead; > IStructuredModel theSharedModel; > boolean initializing = true; >- boolean doWait = true; >+ volatile boolean doWait = true; >+ final Object loadCondition = new Object(); > > SharedObject(IStructuredModel sharedModel) { > theSharedModel = sharedModel; >@@ -121,15 +151,43 @@ > * Waits until this shared object has been attempted to be loaded. > * The load is "attempted" because not all loads result in a model. > * However, upon leaving this method, theShareModel variable >- * is up-to-date. >+ * is up-to-date. Should not be called if holding a lock on this object. > */ >- public synchronized void waitForLoadAttempt() { >- while(initializing) { >- try { >- wait(); >+ public void waitForLoadAttempt() { >+ synchronized(loadCondition) { >+ long start = System.currentTimeMillis(); >+ // Note: A WAIT_DELAY of 0 is infinite >+ int maxTimeMs = Math.max(0, WAIT_DELAY); >+ final int waitInterval = Math.min(250, maxTimeMs); >+ boolean interrupted = false; >+ while (initializing && maxTimeMs >= 0) { >+ try { >+ loadCondition.wait(waitInterval); >+ maxTimeMs -= waitInterval; >+ } >+ catch (InterruptedException e) { >+ interrupted = true; >+ if (ALLOW_INTERRUPT_WAITING_THREAD) { >+ break; >+ } >+ } > } >- catch (InterruptedException e) { >- // ignore interruption! >+ if (initializing) { >+ long totalWaitTime = System.currentTimeMillis() - start; >+ if (interrupted) { >+ throw new OperationCanceledException( >+ "Waiting thread interrupted during simultenous model load. Load aborted. (Waited " >+ + totalWaitTime + "ms)"); >+ } >+ else { >+ throw new OperationCanceledException( >+ "Waiting thread timed-out during simultenous model load. Load aborted. (Waited " >+ + totalWaitTime + "ms)"); >+ } >+ } >+ if (interrupted) { >+ // Propagate (don't swallow) the interrupt >+ Thread.currentThread().interrupt(); > } > } > } >@@ -139,9 +197,11 @@ > * {@link #waitForLoadAttempt()} will proceed after this > * method returns. > */ >- public synchronized void setLoaded() { >- initializing = false; >- notifyAll(); >+ public void setLoaded() { >+ synchronized(loadCondition) { >+ initializing = false; >+ loadCondition.notifyAll(); >+ } > } > } > >@@ -166,6 +226,12 @@ > return instance; > } > >+ public void removePreferenceListener() { >+ InstanceScope scope = new InstanceScope(); >+ IEclipsePreferences instancePrefs = scope.getNode(SSECorePlugin.ID); >+ instancePrefs.removePreferenceChangeListener(LISTENER); >+ } >+ > /** > * Our cache of managed objects > */ >@@ -183,9 +249,12 @@ > ModelManagerImpl() { > super(); > fManagedObjects = new HashMap(); >- // To prevent deadlocks: always acquire multiple locks in this order: SYNC, sharedObject. >- // DO NOT acquire a SYNC within a sharedObject lock, unless you already own the SYNC lock >- // Tip: Try to hold the smallest number of locks you can >+ /** >+ * NOTES: To prevent deadlocks: always acquire multiple locks in this >+ * order: SYNC->sharedObject->sharedObject.loadCondition DO NOT acquire a >+ * SYNC within a sharedObject lock, unless you already own the SYNC lock >+ * Tip: Try to hold the smallest number of locks you can >+ */ > } > > private IStructuredModel _commonCreateModel(IFile file, String id, IModelHandler handler, URIResolver resolver, ReadEditType rwType, EncodingRule encodingRule) throws IOException,CoreException { >@@ -380,7 +449,6 @@ > ((AbstractStructuredModel) model).setContentTypeIdentifier(description.getContentType().getId()); > } > } >- > sharedObject.theSharedModel = model; > _initCount(sharedObject, rwType); > } else { >@@ -1159,10 +1227,10 @@ > // and return the object. > SYNC.release(); > doRelease=false; >+ if (sharedObject.doWait) { >+ sharedObject.waitForLoadAttempt(); >+ } > synchronized(sharedObject) { >- if (sharedObject.doWait) { >- sharedObject.waitForLoadAttempt(); >- } > if (sharedObject.theSharedModel!=null) { > _incrCount(sharedObject, EDIT); > } >@@ -1241,11 +1309,10 @@ > // and return the object. > SYNC.release(); > doRelease=false; >- >+ if (sharedObject.doWait) { >+ sharedObject.waitForLoadAttempt(); >+ } > synchronized(sharedObject) { >- if (sharedObject.doWait) { >- sharedObject.waitForLoadAttempt(); >- } > if (sharedObject.theSharedModel!=null) { > _incrCount(sharedObject, READ); > } >@@ -2098,4 +2165,92 @@ > SYNC.release(); > return inUse; > } >+ >+ private static String getProperty(String property) { >+ // Importance order is: >+ // default-default < instanceScope < configurationScope < systemProperty < envVar >+ String value=null; >+ >+ if (value == null) { >+ value = System.getenv(property); >+ } >+ if (value == null) { >+ value = System.getProperty(property); >+ } >+ if (value==null) { >+ IPreferencesService preferencesService = Platform.getPreferencesService(); >+ IScopeContext[] lookupOrder = new IScopeContext[] { >+ new ConfigurationScope(), new InstanceScope() >+ }; >+ String key = property; >+ if (property != null && property.startsWith(SSECorePlugin.ID)) { >+ // +1, include the "." >+ key = property.substring(SSECorePlugin.ID.length() + 1, property.length()); >+ } >+ preferencesService.getString(SSECorePlugin.ID, key, null, lookupOrder); >+ } >+ >+ return value; >+ } >+ >+ private static String getDefault(String property) { >+ // this is the "default-default" >+ if ("org.eclipse.wst.sse.core.modelmanager.maxWaitDuringConcurrentLoad".equals(property)) { >+ return "0"; >+ } >+ else if ("org.eclipse.wst.sse.core.modelmanager.allowInterruptsDuringConcurrentLoad" >+ .equals(property)) { >+ return "false"; >+ } >+ return null; >+ } >+ >+ private static boolean getBoolean(String key) { >+ String property = getProperty(key); >+ // if (property != null) { >+ // System.out.println("Tweak: " + key + "=" + Boolean.parseBoolean(property)); //$NON-NLS-1$ //$NON-NLS-2$ >+ // } >+ return property != null ? Boolean.parseBoolean(property) : Boolean >+ .parseBoolean(getDefault(key)); >+ } >+ >+ private static int getInt(String key) { >+ String property = getProperty(key); >+ int size = 0; >+ if (property != null) { >+ try { >+ size = Integer.parseInt(property); >+ // System.out.println("Tweak: " + key + "=" + size); //$NON-NLS-1$ //$NON-NLS-2$ >+ } >+ catch (NumberFormatException e) { >+ size = getDefaultInt(key, property, size); >+ } >+ } >+ else { >+ size = getDefaultInt(key, property, size); >+ } >+ return size; >+ } >+ >+ private static int getDefaultInt(String key, String property, int size) { >+ // ignored >+ try { >+ size = Integer.parseInt(getDefault(key)); >+ } >+ catch (NumberFormatException e1) { >+ handleIntParseException(key, property, e1); >+ size = 0; >+ } >+ return size; >+ } >+ >+ private static void handleIntParseException(String key, String property, >+ NumberFormatException e1) { >+ Exception n = new Exception( >+ NLS >+ .bind( >+ "Exception during parse of default value for key ''{0}'' value was ''{1}''. Using 0 instead", //$NON-NLS-1$ >+ key, property), e1); >+ n.printStackTrace(); >+ } > }
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 287096
:
144990
|
145676
|
145681
|
145821
|
145825
|
145829
| 146449 |
147495
|
147502
|
166062
|
166063