diff options
author | Saša Živkov <sasa.zivkov@sap.com> | 2017-07-04 16:35:12 +0200 |
---|---|---|
committer | Saša Živkov <sasa.zivkov@sap.com> | 2017-07-05 11:25:18 +0200 |
commit | bb56657f210c704334ad66723e3a297e1ed37e1b (patch) | |
tree | 4f4de5ddc175eca8a9016ba93a384a4abd439df0 | |
parent | dc18cb665eb452d71602e1a980d7669a67265dfc (diff) |
Fix race condition when scheduling a replication
The state of PushOne object was modified after the operation was scheduled.
Depending on the delay parameter the PushOne.run() could be called before (when
the delay is zero or close to zero) or after (longer delay) the current thread
calls e.addState(ref, state). Thus, the thread executing PushOne.run() may or
may not see the update of its stateMap. Further, the stateMap is a
LinkedListMultimap which is not thread safe and the PushOne doesn't synchronize
access to it.
Change-Id: Ib26a5933a7993a6d2f0501e5daaf06a7892e597f
-rw-r--r-- | src/main/java/com/googlesource/gerrit/plugins/replication/Destination.java | 3 |
1 files changed, 2 insertions, 1 deletions
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/Destination.java b/src/main/java/com/googlesource/gerrit/plugins/replication/Destination.java index 603a70f..dd401af 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/replication/Destination.java +++ b/src/main/java/com/googlesource/gerrit/plugins/replication/Destination.java @@ -295,13 +295,14 @@ public class Destination { if (e == null) { e = opFactory.create(project, uri); addRef(e, ref); + e.addState(ref, state); pool.schedule(e, config.getDelay(), TimeUnit.SECONDS); pending.put(uri, e); } else if (!e.getRefs().contains(ref)) { addRef(e, ref); + e.addState(ref, state); } state.increasePushTaskCount(project.get(), ref); - e.addState(ref, state); repLog.info("scheduled {}:{} => {} to run after {}s", project, ref, e, config.getDelay()); } } |