From 91205bf227e8d5df21e34cd257514886f9a18365 Mon Sep 17 00:00:00 2001 From: huaxiangsun Date: Wed, 24 Mar 2021 14:39:35 -0700 Subject: [PATCH] HBASE-25691 Test failure: TestVerifyBucketCacheFile.testRetrieveFromFile (#3088) The issue is that FileInputStream is created with try-with-resources, so its close() is called right after the try sentence. FileInputStream is a finalize class, when this object is garbage collected, its close() is called again. To avoid this double-free resources, add guard against it. Signed-off-by: stack --- .../hbase/io/hfile/bucket/BucketCache.java | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.java index de44ad7f54e..1f9aac425e2 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.java @@ -1101,14 +1101,27 @@ public class BucketCache implements BlockCache, HeapSize { */ private FileInputStream deleteFileOnClose(final File file) throws IOException { return new FileInputStream(file) { + private File myFile; + private FileInputStream init(File file) { + myFile = file; + return this; + } @Override public void close() throws IOException { - super.close(); - if (!file.delete()) { - throw new IOException("Failed deleting persistence file " + file.getAbsolutePath()); + // close() will be called during try-with-resources and it will be + // called by finalizer thread during GC. To avoid double-free resource, + // set myFile to null after the first call. + if (myFile == null) { + return; } + + super.close(); + if (!myFile.delete()) { + throw new IOException("Failed deleting persistence file " + myFile.getAbsolutePath()); + } + myFile = null; } - }; + }.init(file); } private void verifyCapacityAndClasses(long capacitySize, String ioclass, String mapclass)