fix TrackingScheduledExecutor CME seen with
testMultiTopologyPollWithError() Jenkins #118
diff --git a/runtime/etiao/src/main/java/org/apache/edgent/runtime/etiao/TrackingScheduledExecutor.java b/runtime/etiao/src/main/java/org/apache/edgent/runtime/etiao/TrackingScheduledExecutor.java
index c4dc44d..478e419 100644
--- a/runtime/etiao/src/main/java/org/apache/edgent/runtime/etiao/TrackingScheduledExecutor.java
+++ b/runtime/etiao/src/main/java/org/apache/edgent/runtime/etiao/TrackingScheduledExecutor.java
@@ -118,6 +118,14 @@
private int cancelAllAsyncTasks(boolean mayInterruptIfRunning) {
int notCanceled = 0;
synchronized (asyncTasks) {
+ // hmm have gotten CMEs here with testMultiTopologyPollWithError.
+ // This seems to follow the required access pattern for synchronized collection iterator.
+ // But obviously something's amiss. There seem to be only a few other
+ // asyncTasks modifiers:
+ // trackTask() - add
+ // hasActiveTasks() - iterates while synchronized and can remove
+ // removeTrack() - remove
+ // Just to make things iron clad, synch the add and remove too
for (RunnableScheduledFuture<?> task : asyncTasks) {
if (!task.cancel(mayInterruptIfRunning))
notCanceled++;
@@ -134,7 +142,7 @@
*/
private <V> RunnableScheduledFuture<V> trackTask(RunnableScheduledFuture<V> task) {
task = new TrackedFuture<V>(task);
- asyncTasks.add(task);
+ synchronized(asyncTasks) { asyncTasks.add(task); } // see cancelAllAsyncTasks
return task;
}
@@ -214,7 +222,7 @@
* the scheduler seems to have no work.
*/
private void removeTrack() {
- asyncTasks.remove(this);
+ synchronized(asyncTasks) { asyncTasks.remove(this); } // see cancelAllAsyncTasks
// Notify the completer if the following is true:
// no asyncTasks (user tasks) pending, or the executor's task