INT-4271: FWMH: Fix Race Condition with stop()

JIRA: https://jira.spring.io/browse/INT-4271

The `Flusher.run()` is `synchronized` on the `FWMH`; a `stop()` while it's running will interrupt the task
which could cause a state to be removed without a flush actually happening (interrupt
on lock acquisition).

- synchronize `stop()` so it won't interrupt a running flusher
- detect an interrupt in the flusher and stop flushing


**Cherry-pick to 4.3.x**
This commit is contained in:
Gary Russell
2017-06-19 10:38:24 -04:00
committed by Artem Bilan
parent 404c2c5369
commit a38bf60332

View File

@@ -474,7 +474,7 @@ public class FileWritingMessageHandler extends AbstractReplyProducingMessageHand
} }
@Override @Override
public void stop() { public synchronized void stop() {
if (this.flushTask != null) { if (this.flushTask != null) {
this.flushTask.cancel(true); this.flushTask.cancel(true);
this.flushTask = null; this.flushTask = null;
@@ -1005,7 +1005,7 @@ public class FileWritingMessageHandler extends AbstractReplyProducingMessageHand
this.lock = lock; this.lock = lock;
} }
private void close() { private boolean close() {
try { try {
this.lock.lockInterruptibly(); this.lock.lockInterruptibly();
try { try {
@@ -1019,9 +1019,11 @@ public class FileWritingMessageHandler extends AbstractReplyProducingMessageHand
catch (IOException e) { catch (IOException e) {
// ignore // ignore
} }
return true;
} }
catch (InterruptedException e1) { catch (InterruptedException e1) {
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
return false;
} }
finally { finally {
this.lock.unlock(); this.lock.unlock();
@@ -1047,10 +1049,14 @@ public class FileWritingMessageHandler extends AbstractReplyProducingMessageHand
FileState state = entry.getValue(); FileState state = entry.getValue();
if (state.lastWrite < expired || if (state.lastWrite < expired ||
(!FileWritingMessageHandler.this.flushWhenIdle && state.firstWrite < expired)) { (!FileWritingMessageHandler.this.flushWhenIdle && state.firstWrite < expired)) {
iterator.remove(); if (state.close()) {
state.close(); if (FileWritingMessageHandler.this.logger.isDebugEnabled()) {
if (FileWritingMessageHandler.this.logger.isDebugEnabled()) { FileWritingMessageHandler.this.logger.debug("Flushed: " + entry.getKey());
FileWritingMessageHandler.this.logger.debug("Flushed: " + entry.getKey()); }
iterator.remove();
}
else {
break; // interrupted
} }
} }
} }