From c86a8beabdf7910f0ddd298f617b78e642985678 Mon Sep 17 00:00:00 2001
From: Simon Barner <barner@fortiss.org>
Date: Fri, 22 Oct 2021 15:53:17 +0200
Subject: [PATCH] Prevent deadlock between "model checker" and workspace change
 service

* Persistency service lock
* Lock of working queue with files to be checked for validity

Issue-Ref: 4166
Issue-Url: https://git.fortiss.org/af3/af3/-/issues/4166

Signed-off-by: Simon Barner <barner@fortiss.org>
---
 .../tooling/kernel/ui/internal/.ratings       |  2 +-
 .../kernel/ui/internal/MarkerService.java     | 43 +++++++------------
 2 files changed, 16 insertions(+), 29 deletions(-)

diff --git a/org.fortiss.tooling.kernel.ui/src/org/fortiss/tooling/kernel/ui/internal/.ratings b/org.fortiss.tooling.kernel.ui/src/org/fortiss/tooling/kernel/ui/internal/.ratings
index a72461b88..c99eb835b 100644
--- a/org.fortiss.tooling.kernel.ui/src/org/fortiss/tooling/kernel/ui/internal/.ratings
+++ b/org.fortiss.tooling.kernel.ui/src/org/fortiss/tooling/kernel/ui/internal/.ratings
@@ -2,7 +2,7 @@ ActionService.java e29126b5947c9fd2f1d82bb87001b9d0ead50c3b GREEN
 AllocationEditPartFactoryService.java 1656319f018b4df6d18643e2eb76e012f45c2392 GREEN
 ContextMenuService.java 802b6d0ade78f91478cd8959cfb423b9963d43bf GREEN
 EditPartFactoryService.java 14c44fd426da4a26bfd4012652ea510a4b149421 GREEN
-MarkerService.java 505296c356f8d66c5c009b6d6181a971d02a9501 GREEN
+MarkerService.java a55e049097d18e419464a09e6f8330b65348cc36 YELLOW
 ModelEditorBindingService.java 52038a912db203fb8d63a000a59872cfa94e0eea GREEN
 ModelElementHandlerService.java 34adeef844bf98c69f1b9a7252f34d0a2b741b54 GREEN
 NavigatorService.java 1d773dde3791ddf7051616fe249558e7e307757d GREEN
diff --git a/org.fortiss.tooling.kernel.ui/src/org/fortiss/tooling/kernel/ui/internal/MarkerService.java b/org.fortiss.tooling.kernel.ui/src/org/fortiss/tooling/kernel/ui/internal/MarkerService.java
index 505296c35..a55e04909 100644
--- a/org.fortiss.tooling.kernel.ui/src/org/fortiss/tooling/kernel/ui/internal/MarkerService.java
+++ b/org.fortiss.tooling.kernel.ui/src/org/fortiss/tooling/kernel/ui/internal/MarkerService.java
@@ -25,10 +25,11 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.Queue;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentLinkedQueue;
 
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.IStatus;
@@ -87,11 +88,9 @@ public class MarkerService implements IMarkerService, IPersistencyServiceListene
 		}
 	};
 
-	/**
-	 * List of invalid top-level elements to be refreshed by the constraint
-	 * checker job.
-	 */
-	private final List<ITopLevelElement> invalidElements = new LinkedList<ITopLevelElement>();
+	/** Invalid top-level elements to be refreshed by the constraint checker job. */
+	private final Queue<ITopLevelElement> invalidElements =
+			new ConcurrentLinkedQueue<ITopLevelElement>();
 
 	/** Stores the marker view. */
 	private ErrorViewFXLayoutController markerController;
@@ -101,29 +100,19 @@ public class MarkerService implements IMarkerService, IPersistencyServiceListene
 
 		@Override
 		protected IStatus run(IProgressMonitor monitor) {
-			ITopLevelElement toBeRefreshed;
-			// get next element to be refreshed
-			synchronized(invalidElements) {
-				if(invalidElements.isEmpty()) {
-					return Status.OK_STATUS;
-				}
-				toBeRefreshed = invalidElements.remove(0);
-			}
-			while(toBeRefreshed != null) {
+
+			do {
 				if(monitor.isCanceled()) {
 					return Status.CANCEL_STATUS;
 				}
-				refreshMarkers(toBeRefreshed);
-				// get next element to be refreshed
-				synchronized(invalidElements) {
-					if(invalidElements.isEmpty()) {
-						toBeRefreshed = null;
-					} else {
-						toBeRefreshed = invalidElements.remove(0);
-					}
+
+				ITopLevelElement toBeRefreshed = invalidElements.poll();
+				if(toBeRefreshed == null) {
+					return Status.OK_STATUS;
 				}
-			}
-			return Status.OK_STATUS;
+
+				refreshMarkers(toBeRefreshed);
+			} while(true);
 		}
 	};
 
@@ -226,9 +215,7 @@ public class MarkerService implements IMarkerService, IPersistencyServiceListene
 
 	/** Schedules the given element for constraint checking. */
 	private void doConstraintCheck(ITopLevelElement element) {
-		synchronized(invalidElements) {
-			invalidElements.add(element);
-		}
+		invalidElements.add(element);
 		constraintCheckerJob.schedule();
 	}
 
-- 
GitLab