This is an automated email from the ASF dual-hosted git repository.
frankvicky pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/kafka.git
The following commit(s) were added to refs/heads/trunk by this push:
new e2500186cbf KAFKA-19334 MetadataShell execution unintentionally
deletes lock file (#19817)
e2500186cbf is described below
commit e2500186cbf79d48f163268117e9e75f10a5e53c
Author: Okada Haruki <[email protected]>
AuthorDate: Mon Jun 9 13:24:26 2025 +0900
KAFKA-19334 MetadataShell execution unintentionally deletes lock file
(#19817)
## Summary
- MetadataShell may deletes lock file unintentionally when it exists or
fails to acquire lock. If there's running server, this causes unexpected
result as below:
* MetadataShell succeeds on 2nd run unexpectedly
* Even worse, LogManager/RaftManager's lock also no longer work from
concurrent Kafka process startup
Reviewers: TengYao Chi <[email protected]>
---
.../main/java/org/apache/kafka/server/util/FileLock.java | 8 ++++++++
.../main/java/org/apache/kafka/shell/MetadataShell.java | 6 +++---
.../apache/kafka/shell/MetadataShellIntegrationTest.java | 16 ++++++++++------
3 files changed, 21 insertions(+), 9 deletions(-)
diff --git
a/server-common/src/main/java/org/apache/kafka/server/util/FileLock.java
b/server-common/src/main/java/org/apache/kafka/server/util/FileLock.java
index 4f55b4aebcd..b06f239183a 100644
--- a/server-common/src/main/java/org/apache/kafka/server/util/FileLock.java
+++ b/server-common/src/main/java/org/apache/kafka/server/util/FileLock.java
@@ -91,4 +91,12 @@ public class FileLock {
}
channel.close();
}
+
+ /**
+ * Unlock the file and close the associated FileChannel
+ */
+ public synchronized void unlockAndClose() throws IOException {
+ unlock();
+ channel.close();
+ }
}
diff --git a/shell/src/main/java/org/apache/kafka/shell/MetadataShell.java
b/shell/src/main/java/org/apache/kafka/shell/MetadataShell.java
index 6812bd0cc62..7af9557381d 100644
--- a/shell/src/main/java/org/apache/kafka/shell/MetadataShell.java
+++ b/shell/src/main/java/org/apache/kafka/shell/MetadataShell.java
@@ -114,7 +114,7 @@ public final class MetadataShell {
"directory before proceeding.");
}
} catch (Throwable e) {
- fileLock.destroy();
+ fileLock.unlockAndClose();
throw e;
}
return fileLock;
@@ -186,9 +186,9 @@ public final class MetadataShell {
Utils.closeQuietly(snapshotFileReader, "snapshotFileReader");
if (fileLock != null) {
try {
- fileLock.destroy();
+ fileLock.unlockAndClose();
} catch (Exception e) {
- log.error("Error destroying fileLock", e);
+ log.error("Error cleaning up fileLock", e);
} finally {
fileLock = null;
}
diff --git
a/shell/src/test/java/org/apache/kafka/shell/MetadataShellIntegrationTest.java
b/shell/src/test/java/org/apache/kafka/shell/MetadataShellIntegrationTest.java
index 0b65d96ab43..6a9c1c769dd 100644
---
a/shell/src/test/java/org/apache/kafka/shell/MetadataShellIntegrationTest.java
+++
b/shell/src/test/java/org/apache/kafka/shell/MetadataShellIntegrationTest.java
@@ -97,12 +97,16 @@ public class MetadataShellIntegrationTest {
FileLock fileLock = new FileLock(new File(env.tempDir,
".lock"));
try {
fileLock.lock();
- assertEquals("Unable to lock " +
env.tempDir.getAbsolutePath() +
- ". Please ensure that no broker or controller process
is using this " +
- "directory before proceeding.",
- assertThrows(RuntimeException.class,
- () -> env.shell.run(List.of())).
- getMessage());
+ // We had a bug where the shell can lock the directory
unintentionally
+ // at the 2nd run, so we check that it fails (See
KAFKA-19334)
+ for (int i = 0; i < 2; i++) {
+ assertEquals("Unable to lock " +
env.tempDir.getAbsolutePath() +
+ ". Please ensure that no broker or
controller process is using this " +
+ "directory before proceeding.",
+ assertThrows(RuntimeException.class,
+ () ->
env.shell.run(List.of())).
+ getMessage());
+ }
} finally {
fileLock.destroy();
}