LockRegistryLeaderInitiatorTests race condition
There is tiny time window when `LockRegistryLeaderInitiator` can be stopped during `Context.yield()` invocation. In this case the `LockRegistryLeaderInitiator` goes to the stopped state, but a new `leaderSelector` is submitted for election. Therefore in the `LockRegistryLeaderInitiatorTests.competing()` the second initiator may not get be granted because there is uncontrolled `leaderSelector` task on background. We can overcome it with always `this.initiator.stop()` for the `LockRegistryLeaderInitiatorTests`, but to be sure in the fix it would be better to leave as is. Also add `@Rule Log4jLevelAdjuster` for future diagnostics **Cherry-pick to 4.3.x**
This commit is contained in:
@@ -200,7 +200,9 @@ public class LockRegistryLeaderInitiator implements SmartLifecycle, DisposableBe
|
||||
*/
|
||||
@Override
|
||||
public boolean isRunning() {
|
||||
return this.running;
|
||||
synchronized (this.lifecycleMonitor) {
|
||||
return this.running;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -399,9 +401,11 @@ public class LockRegistryLeaderInitiator implements SmartLifecycle, DisposableBe
|
||||
public void yield() {
|
||||
if (LockRegistryLeaderInitiator.this.future != null) {
|
||||
LockRegistryLeaderInitiator.this.future.cancel(true);
|
||||
LockRegistryLeaderInitiator.this.future =
|
||||
LockRegistryLeaderInitiator.this.executorService
|
||||
.submit(LockRegistryLeaderInitiator.this.leaderSelector);
|
||||
if (isRunning()) {
|
||||
LockRegistryLeaderInitiator.this.future =
|
||||
LockRegistryLeaderInitiator.this.executorService
|
||||
.submit(LockRegistryLeaderInitiator.this.leaderSelector);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,9 @@ import static org.junit.Assert.assertThat;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.log4j.Level;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.integration.leader.Context;
|
||||
@@ -30,27 +32,33 @@ import org.springframework.integration.leader.DefaultCandidate;
|
||||
import org.springframework.integration.leader.event.LeaderEventPublisher;
|
||||
import org.springframework.integration.support.locks.DefaultLockRegistry;
|
||||
import org.springframework.integration.support.locks.LockRegistry;
|
||||
import org.springframework.integration.test.rule.Log4jLevelAdjuster;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
* @author Artem Bilan
|
||||
*
|
||||
* @since 4.3.1
|
||||
*/
|
||||
public class LockRegistryLeaderInitiatorTests {
|
||||
|
||||
private CountDownLatch granted = new CountDownLatch(1);
|
||||
@Rule
|
||||
public Log4jLevelAdjuster adjuster = new Log4jLevelAdjuster(Level.TRACE, "org.springframework.integration");
|
||||
|
||||
private CountDownLatch revoked = new CountDownLatch(1);
|
||||
private CountDownLatch granted;
|
||||
|
||||
private CountDownLatch revoked;
|
||||
|
||||
private LockRegistry registry = new DefaultLockRegistry();
|
||||
|
||||
private CountingPublisher publisher = new CountingPublisher(this.granted, this.revoked);
|
||||
|
||||
private LockRegistryLeaderInitiator initiator =
|
||||
new LockRegistryLeaderInitiator(this.registry, new DefaultCandidate());
|
||||
|
||||
@Before
|
||||
public void init() {
|
||||
this.initiator.setLeaderEventPublisher(this.publisher);
|
||||
this.granted = new CountDownLatch(1);
|
||||
this.revoked = new CountDownLatch(1);
|
||||
this.initiator.setLeaderEventPublisher(new CountingPublisher(this.granted, this.revoked));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user