Skip to content

Commit e41072e

Browse files
committed
Cleanup: attempt to fix race condition.
The latestCommitFuture is global, but was not protected against concurrent modifications. Code changes: * Make sure that adding the commit to the queue and queueing the new job on the executor happen synchronized. * Eliminate the global latestCommitFuture altogether. It's good enough to wait for the current transactions' commit future.
1 parent cb2f319 commit e41072e

File tree

3 files changed

+24
-24
lines changed

3 files changed

+24
-24
lines changed

src/main/java/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationBusiness.java

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public class ScmSyncConfigurationBusiness {
4747
/*package*/ final ExecutorService writer = Executors.newFixedThreadPool(1, new DaemonThreadFactory());
4848

4949
// TODO: Refactor this into the plugin object ???
50-
private List<Commit> commitsQueue = Collections.synchronizedList(new ArrayList<Commit>());
50+
private List<Commit> commitsQueue = new ArrayList<Commit>();
5151

5252
public ScmSyncConfigurationBusiness(){
5353
}
@@ -139,21 +139,26 @@ public Future<Void> queueChangeSet(final ScmContext scmContext, ChangeSet change
139139

140140
Commit commit = new Commit(changeset, user, userMessage, scmContext);
141141
LOGGER.finest("Queuing commit "+commit.toString()+" to SCM ...");
142-
commitsQueue.add(commit);
143-
144-
return writer.submit(new Callable<Void>() {
145-
public Void call() throws Exception {
146-
processCommitsQueue();
147-
return null;
148-
}
149-
});
142+
synchronized(commitsQueue) {
143+
commitsQueue.add(commit);
144+
145+
return writer.submit(new Callable<Void>() {
146+
public Void call() throws Exception {
147+
processCommitsQueue();
148+
return null;
149+
}
150+
});
151+
}
150152
}
151153

152154
private void processCommitsQueue() {
153155
File scmRoot = new File(getCheckoutScmDirectoryAbsolutePath());
154156

155157
// Copying shared commitQueue in order to allow conccurrent modification
156-
List<Commit> currentCommitQueue = new ArrayList<Commit>(commitsQueue);
158+
List<Commit> currentCommitQueue;
159+
synchronized (commitsQueue) {
160+
currentCommitQueue = new ArrayList<Commit>(commitsQueue);
161+
}
157162
List<Commit> checkedInCommits = new ArrayList<Commit>();
158163

159164
try {
@@ -227,7 +232,9 @@ private void processCommitsQueue() {
227232
signal(e.getMessage(), false);
228233
} finally {
229234
// We should remove every checkedInCommits
230-
commitsQueue.removeAll(checkedInCommits);
235+
synchronized (commitsQueue) {
236+
commitsQueue.removeAll(checkedInCommits);
237+
}
231238
}
232239
}
233240

src/main/java/hudson/plugins/scm_sync_configuration/ScmSyncConfigurationPlugin.java

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,6 @@ public static interface AtomicTransactionFactory {
105105
*/
106106
private transient ThreadLocal<ScmTransaction> transaction = new ThreadLocal<ScmTransaction>();
107107

108-
private transient Future<Void> latestCommitFuture;
109-
110108
private String scmRepositoryUrl;
111109
private SCM scm;
112110
private boolean noUserCommitMessage;
@@ -434,8 +432,7 @@ public void startThreadedTransaction(){
434432
public Future<Void> commitChangeset(ChangeSet changeset){
435433
try {
436434
if(!changeset.isEmpty()){
437-
latestCommitFuture = this.business.queueChangeSet(createScmContext(), changeset, getCurrentUser(), ScmSyncConfigurationDataProvider.retrieveComment(false));
438-
return latestCommitFuture;
435+
return this.business.queueChangeSet(createScmContext(), changeset, getCurrentUser(), ScmSyncConfigurationDataProvider.retrieveComment(false));
439436
} else {
440437
return null;
441438
}
@@ -462,10 +459,6 @@ protected void setTransaction(ScmTransaction transactionToRegister){
462459
public boolean currentUserCannotPurgeFailLogs() {
463460
return !business.canCurrentUserPurgeFailLogs();
464461
}
465-
466-
public Future<Void> getLatestCommitFuture() {
467-
return latestCommitFuture;
468-
}
469462

470463
private static final Pattern STARTS_WITH_DRIVE_LETTER = Pattern.compile("^[a-zA-Z]:");
471464

src/main/java/hudson/plugins/scm_sync_configuration/transactions/ScmTransaction.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package hudson.plugins.scm_sync_configuration.transactions;
22

33
import java.io.File;
4+
import java.util.concurrent.Future;
45

56
import hudson.plugins.scm_sync_configuration.JenkinsFilesHelper;
67
import hudson.plugins.scm_sync_configuration.ScmSyncConfigurationPlugin;
@@ -30,12 +31,11 @@ public void defineCommitMessage(WeightedMessage weightedMessage){
3031
}
3132

3233
public void commit(){
33-
ScmSyncConfigurationPlugin.getInstance().commitChangeset(changeset);
34-
if(synchronousCommit){
35-
// Synchronous transactions should wait for latest commit future to be fully processed
36-
// before going further
34+
Future<Void> future = ScmSyncConfigurationPlugin.getInstance().commitChangeset(changeset);
35+
if (synchronousCommit && future != null) {
36+
// Synchronous transactions should wait for the future to be fully processed
3737
try {
38-
ScmSyncConfigurationPlugin.getInstance().getLatestCommitFuture().get();
38+
future.get();
3939
} catch (Exception e) {
4040
throw new RuntimeException(e);
4141
}

0 commit comments

Comments
 (0)