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());
+ }
+ }
}