Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEike Stepper2020-02-26 16:15:14 +0000
committerEike Stepper2020-02-26 16:15:14 +0000
commit17712c8490d2244692a4f3bac37964243da5deca (patch)
tree099aa7dc868de3ff44c2ff526793894d034830ad
parent365fc13139761df7f1dac307b0c9a13fdb940409 (diff)
downloadcdo-17712c8490d2244692a4f3bac37964243da5deca.tar.gz
cdo-17712c8490d2244692a4f3bac37964243da5deca.tar.xz
cdo-17712c8490d2244692a4f3bac37964243da5deca.zip
[560280] Possible deadlock during the session invalidation
https://bugs.eclipse.org/bugs/show_bug.cgi?id=560280
-rw-r--r--plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_560280_Test.java2
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOSessionImpl.java86
2 files changed, 58 insertions, 30 deletions
diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_560280_Test.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_560280_Test.java
index a50217df01..410ba1a517 100644
--- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_560280_Test.java
+++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_560280_Test.java
@@ -44,6 +44,7 @@ import org.eclipse.net4j.util.security.IPasswordCredentialsProvider;
import org.eclipse.net4j.util.security.PasswordCredentials;
import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.emf.spi.cdo.CDOMergingConflictResolver;
import org.eclipse.emf.spi.cdo.InternalCDOSession;
import java.util.Map;
@@ -136,6 +137,7 @@ public class Bugzilla_560280_Test extends AbstractCDOTest
CDOSession sessionUnderTest = openSession();
CDOTransaction transactionUnderTest = sessionUnderTest.openTransaction();
+ transactionUnderTest.options().addConflictResolver(new CDOMergingConflictResolver());
try
{
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOSessionImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOSessionImpl.java
index 0805f41159..984df32feb 100644
--- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOSessionImpl.java
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOSessionImpl.java
@@ -152,7 +152,9 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.Queue;
import java.util.Set;
+import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutorService;
/**
@@ -1952,7 +1954,9 @@ public abstract class CDOSessionImpl extends CDOTransactionContainerImpl impleme
{
private final Set<Object> unfinishedLocalCommits = new HashSet<>();
- private final List<SessionInvalidation> reorderQueue = new ArrayList<>();
+ private final List<SessionInvalidation> invalidationQueue = new ArrayList<>();
+
+ private final Queue<Runnable> postInvalidationQueue = new ConcurrentLinkedQueue<>();
private int lastCommitNumber;
@@ -1988,23 +1992,44 @@ public abstract class CDOSessionImpl extends CDOTransactionContainerImpl impleme
unfinishedLocalCommits.remove(token);
}
- public synchronized void scheduleInvalidations(InvalidationData invalidationData)
+ public void scheduleInvalidations(InvalidationData invalidationData)
{
SessionInvalidation invalidation = new SessionInvalidation(invalidationData);
- reorderQueue.add(invalidation);
- Collections.sort(reorderQueue);
-
- if (DEBUG_INVALIDATION)
+ synchronized (this)
{
- IOUtil.OUT().println(CDOSessionImpl.this + " [" + getLastUpdateTime() % 10000 + "] " + invalidation.getPreviousTimeStamp() % 10000 + " --> "
- + invalidation.getTimeStamp() % 10000 + " reorderQueue=" + reorderQueue + " unfinishedLocalCommits=" + unfinishedLocalCommits);
+ invalidationQueue.add(invalidation);
+ Collections.sort(invalidationQueue);
+
+ if (DEBUG_INVALIDATION)
+ {
+ IOUtil.OUT().println(CDOSessionImpl.this + " [" + getLastUpdateTime() % 10000 + "] " + invalidation.getPreviousTimeStamp() % 10000 + " --> "
+ + invalidation.getTimeStamp() % 10000 + " reorderQueue=" + invalidationQueue + " unfinishedLocalCommits=" + unfinishedLocalCommits);
+ }
}
- while (isActive() && !reorderQueue.isEmpty() && canProcess(reorderQueue.get(0)))
+ while (isActive())
{
- SessionInvalidation invalidation0 = reorderQueue.remove(0);
- invalidation0.process();
+ synchronized (this)
+ {
+ if (invalidationQueue.isEmpty() || !canProcess(invalidationQueue.get(0)))
+ {
+ break;
+ }
+
+ SessionInvalidation invalidation0 = invalidationQueue.remove(0);
+ Runnable postInvalidationRunnable = invalidation0.process();
+ if (postInvalidationRunnable != null)
+ {
+ postInvalidationQueue.add(postInvalidationRunnable);
+ }
+ }
+
+ Runnable postInvalidationRunnable;
+ while ((postInvalidationRunnable = postInvalidationQueue.poll()) != null)
+ {
+ postInvalidationRunnable.run();
+ }
}
}
@@ -2058,7 +2083,7 @@ public abstract class CDOSessionImpl extends CDOTransactionContainerImpl impleme
return Long.toString(getTimeStamp() % 10000);
}
- public void process()
+ public Runnable process()
{
long timeStamp = getTimeStamp();
@@ -2092,21 +2117,26 @@ public abstract class CDOSessionImpl extends CDOTransactionContainerImpl impleme
setLastUpdateTime(timeStamp);
}
- CDOLockChangeInfo lockChangeInfo = invalidationData.getLockChangeInfo();
- InternalCDOTransaction sender = invalidationData.getSender();
+ Map<CDORevision, CDOPermission> oldPermissionsFinal = oldPermissions;
+ Map<CDOID, InternalCDORevision> oldRevisionsFinal = oldRevisions;
- if (success)
- {
- fireEvent(new SessionInvalidationEvent(sender, commitInfo, invalidationData.getSecurityImpact(), oldPermissions));
- fireEvent(new SessionLocksChangedEvent(sender, lockChangeInfo));
+ return () -> {
+ CDOLockChangeInfo lockChangeInfo = invalidationData.getLockChangeInfo();
+ InternalCDOTransaction sender = invalidationData.getSender();
- commitInfoManager.notifyCommitInfoHandlers(commitInfo);
- }
+ if (success)
+ {
+ fireEvent(new SessionInvalidationEvent(sender, commitInfo, invalidationData.getSecurityImpact(), oldPermissionsFinal));
+ fireEvent(new SessionLocksChangedEvent(sender, lockChangeInfo));
- for (InternalCDOView view : views)
- {
- invalidateView(commitInfo, view, sender, oldRevisions, invalidationData.isClearResourcePathCache(), lockChangeInfo);
- }
+ commitInfoManager.notifyCommitInfoHandlers(commitInfo);
+ }
+
+ for (InternalCDOView view : views)
+ {
+ invalidateView(commitInfo, view, sender, oldRevisionsFinal, invalidationData.isClearResourcePathCache(), lockChangeInfo);
+ }
+ };
}
catch (RuntimeException ex)
{
@@ -2120,12 +2150,8 @@ public abstract class CDOSessionImpl extends CDOTransactionContainerImpl impleme
TRACER.trace(Messages.getString("CDOSessionImpl.2")); //$NON-NLS-1$
}
}
- finally
- {
- // setLastUpdateTime() is not synchronized with the Invalidator.
- // Give the Invalidator another chance to schedule Invalidations.
- // invalidator.scheduleInvalidations();
- }
+
+ return null;
}
private Map<CDOID, InternalCDORevision> reviseRevisions()

Back to the top