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