From b7b06a5f3425f5ca6c34e5d0ac60105aae61a899 Mon Sep 17 00:00:00 2001 From: Chris Nauroth Date: Wed, 28 Sep 2016 15:53:17 -0700 Subject: [PATCH] HADOOP-13599. s3a close() to be non-synchronized, so avoid risk of deadlock on shutdown. Contributed by Steve Loughran. (cherry picked from commit 47f80922dc7cb2fa6d084e6fb1f354c4ec1d4c69) (cherry picked from commit 1f1e47e41198760b0ddddceb489f2de2b569f38a) --- .../main/java/org/apache/hadoop/fs/s3a/S3AFileSystem.java | 7 ++++++- .../org/apache/hadoop/fs/s3a/TestS3AConfiguration.java | 8 ++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/S3AFileSystem.java b/hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/S3AFileSystem.java index 0c5e569a1ca..a7e36e4cf30 100644 --- a/hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/S3AFileSystem.java +++ b/hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/S3AFileSystem.java @@ -127,6 +127,7 @@ public class S3AFileSystem extends FileSystem { private S3AInputPolicy inputPolicy; private static final AtomicBoolean warnedOfCoreThreadDeprecation = new AtomicBoolean(false); + private final AtomicBoolean closed = new AtomicBoolean(false); // The maximum number of entries that can be deleted in any call to s3 private static final int MAX_ENTRIES_TO_DELETE = 1000; @@ -1514,7 +1515,11 @@ public class S3AFileSystem extends FileSystem { * @throws IOException IO problem */ @Override - public synchronized void close() throws IOException { + public void close() throws IOException { + if (closed.getAndSet(true)) { + // already closed + return; + } try { super.close(); } finally { diff --git a/hadoop-tools/hadoop-aws/src/test/java/org/apache/hadoop/fs/s3a/TestS3AConfiguration.java b/hadoop-tools/hadoop-aws/src/test/java/org/apache/hadoop/fs/s3a/TestS3AConfiguration.java index 3f9a99f4cd3..99934a55a53 100644 --- a/hadoop-tools/hadoop-aws/src/test/java/org/apache/hadoop/fs/s3a/TestS3AConfiguration.java +++ b/hadoop-tools/hadoop-aws/src/test/java/org/apache/hadoop/fs/s3a/TestS3AConfiguration.java @@ -401,6 +401,14 @@ public class TestS3AConfiguration { awsConf.getUserAgent()); } + @Test + public void testCloseIdempotent() throws Throwable { + conf = new Configuration(); + fs = S3ATestUtils.createTestFileSystem(conf); + fs.close(); + fs.close(); + } + /** * Reads and returns a field from an object using reflection. If the field * cannot be found, is null, or is not the expected type, then this method