You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by dn...@apache.org on 2020/07/09 13:14:18 UTC

[lucene-solr] branch master updated: LUCENE-9423: Handle exc in NIOFSDirectory#openInput (#1658)

This is an automated email from the ASF dual-hosted git repository.

dnhatn pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/lucene-solr.git


The following commit(s) were added to refs/heads/master by this push:
     new 20ec57a  LUCENE-9423: Handle exc in NIOFSDirectory#openInput (#1658)
20ec57a is described below

commit 20ec57a4fed3a6a691eca6c76a8e0e8977d5eb63
Author: Nhat Nguyen <nh...@elastic.co>
AuthorDate: Thu Jul 9 09:14:05 2020 -0400

    LUCENE-9423: Handle exc in NIOFSDirectory#openInput (#1658)
    
    If we fail to get the size of a file in the constructor of
    NIOFSIndexInput, then we will leak a FileChannel opened in
    NIOFSDirectory#openInput.
---
 .../org/apache/lucene/store/NIOFSDirectory.java    | 13 +++++++-
 .../apache/lucene/store/TestNIOFSDirectory.java    | 35 ++++++++++++++++++++++
 2 files changed, 47 insertions(+), 1 deletion(-)

diff --git a/lucene/core/src/java/org/apache/lucene/store/NIOFSDirectory.java b/lucene/core/src/java/org/apache/lucene/store/NIOFSDirectory.java
index dd44025..d96f11c 100644
--- a/lucene/core/src/java/org/apache/lucene/store/NIOFSDirectory.java
+++ b/lucene/core/src/java/org/apache/lucene/store/NIOFSDirectory.java
@@ -25,6 +25,8 @@ import java.nio.file.Path;
 import java.nio.file.StandardOpenOption;
 import java.util.concurrent.Future; // javadoc
 
+import org.apache.lucene.util.IOUtils;
+
 /**
  * An {@link FSDirectory} implementation that uses java.nio's FileChannel's
  * positional read, which allows multiple threads to read from the same file
@@ -79,7 +81,16 @@ public class NIOFSDirectory extends FSDirectory {
     ensureCanRead(name);
     Path path = getDirectory().resolve(name);
     FileChannel fc = FileChannel.open(path, StandardOpenOption.READ);
-    return new NIOFSIndexInput("NIOFSIndexInput(path=\"" + path + "\")", fc, context);
+    boolean success = false;
+    try {
+      final NIOFSIndexInput indexInput = new NIOFSIndexInput("NIOFSIndexInput(path=\"" + path + "\")", fc, context);
+      success = true;
+      return indexInput;
+    } finally {
+      if (success == false) {
+        IOUtils.closeWhileHandlingException(fc);
+      }
+    }
   }
   
   /**
diff --git a/lucene/core/src/test/org/apache/lucene/store/TestNIOFSDirectory.java b/lucene/core/src/test/org/apache/lucene/store/TestNIOFSDirectory.java
index ae559a7..dc831b6 100644
--- a/lucene/core/src/test/org/apache/lucene/store/TestNIOFSDirectory.java
+++ b/lucene/core/src/test/org/apache/lucene/store/TestNIOFSDirectory.java
@@ -18,7 +18,17 @@ package org.apache.lucene.store;
 
 
 import java.io.IOException;
+import java.net.URI;
+import java.nio.channels.FileChannel;
+import java.nio.file.FileSystem;
+import java.nio.file.OpenOption;
 import java.nio.file.Path;
+import java.nio.file.attribute.FileAttribute;
+import java.util.Set;
+
+import org.apache.lucene.mockfile.FilterFileChannel;
+import org.apache.lucene.mockfile.FilterPath;
+import org.apache.lucene.mockfile.LeakFS;
 
 /**
  * Tests NIOFSDirectory
@@ -29,4 +39,29 @@ public class TestNIOFSDirectory extends BaseDirectoryTestCase {
   protected Directory getDirectory(Path path) throws IOException {
     return new NIOFSDirectory(path);
   }
+
+  public void testHandleExceptionInConstructor() throws Exception {
+    Path path = createTempDir().toRealPath();
+    final LeakFS leakFS = new LeakFS(path.getFileSystem()) {
+      @Override
+      public FileChannel newFileChannel(Path path, Set<? extends OpenOption> options,
+                                        FileAttribute<?>... attrs) throws IOException {
+        return new FilterFileChannel(super.newFileChannel(path, options, attrs)) {
+          @Override
+          public long size() throws IOException {
+            throw new IOException("simulated");
+          }
+        };
+      }
+    };
+    FileSystem fs = leakFS.getFileSystem(URI.create("file:///"));
+    Path wrapped = new FilterPath(path, fs);
+    try (Directory dir = new NIOFSDirectory(wrapped)) {
+      try (IndexOutput out = dir.createOutput("test.bin", IOContext.DEFAULT)) {
+        out.writeString("hello");
+      }
+      final IOException error = expectThrows(IOException.class, () -> dir.openInput("test.bin", IOContext.DEFAULT));
+      assertEquals("simulated", error.getMessage());
+    }
+  }
 }