Skip to content

Commit 15fc23c

Browse files
artembilangaryrussell
authored andcommitted
INT-4447: LockRegLeaderInit: Catch unlock errors
JIRA: https://jira.spring.io/browse/INT-4447 When we get an exception during `this.lock.unlock()`, we don't revoke leadership. In case of external resource (e.g. JDBC) this may cause a race condition when the second candidate is selected as leader when connection comes back * Catch `this.lock.unlock()` exceptions and log them under DEBUG. This way we proceed to the `handleRevoked()` logic **Cherry-pick to 5.0.x and 4.3.x**
1 parent 4e15772 commit 15fc23c

File tree

2 files changed

+44
-3
lines changed

2 files changed

+44
-3
lines changed

spring-integration-core/src/main/java/org/springframework/integration/support/leader/LockRegistryLeaderInitiator.java

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -381,8 +381,15 @@ else if (acquired) {
381381
}
382382
catch (Exception e) {
383383
if (this.locked) {
384-
this.lock.unlock();
385384
this.locked = false;
385+
try {
386+
this.lock.unlock();
387+
}
388+
catch (Exception e1) {
389+
logger.debug("Could not unlock - treat as broken. " +
390+
"Revoking " + (isRunning() ? " and retrying..." : "..."), e);
391+
392+
}
386393
// The lock was broken and we are no longer leader
387394
handleRevoked();
388395
if (isRunning()) {
@@ -408,11 +415,16 @@ else if (logger.isDebugEnabled()) {
408415
}
409416
finally {
410417
if (this.locked) {
411-
this.lock.unlock();
418+
this.locked = false;
419+
try {
420+
this.lock.unlock();
421+
}
422+
catch (Exception e) {
423+
logger.debug("Could not unlock during stop - treat as broken. Revoking...", e);
424+
}
412425
// We are stopping, therefore not leading any more
413426
handleRevoked();
414427
}
415-
this.locked = false;
416428
}
417429
return null;
418430
}

spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/leader/JdbcLockRegistryLeaderInitiatorTests.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,35 @@ public void publishOnRevoked(Object source, Context context, String role) {
167167
initiator1.stop();
168168
}
169169

170+
@Test
171+
public void testLostConnection() throws InterruptedException {
172+
CountDownLatch granted = new CountDownLatch(1);
173+
CountingPublisher countingPublisher = new CountingPublisher(granted);
174+
175+
DefaultLockRepository lockRepository = new DefaultLockRepository(dataSource);
176+
lockRepository.afterPropertiesSet();
177+
LockRegistryLeaderInitiator initiator = new LockRegistryLeaderInitiator(new JdbcLockRegistry(lockRepository));
178+
initiator.setLeaderEventPublisher(countingPublisher);
179+
180+
initiator.start();
181+
182+
assertThat(granted.await(10, TimeUnit.SECONDS), is(true));
183+
184+
destroy();
185+
186+
assertThat(countingPublisher.revoked.await(10, TimeUnit.SECONDS), is(true));
187+
188+
granted = new CountDownLatch(1);
189+
countingPublisher = new CountingPublisher(granted);
190+
initiator.setLeaderEventPublisher(countingPublisher);
191+
192+
init();
193+
194+
assertThat(granted.await(10, TimeUnit.SECONDS), is(true));
195+
196+
initiator.stop();
197+
}
198+
170199
private static class CountingPublisher implements LeaderEventPublisher {
171200

172201
private final CountDownLatch granted;

0 commit comments

Comments
 (0)