diff --git a/lucene/core/src/java/org/apache/lucene/util/IOUtils.java b/lucene/core/src/java/org/apache/lucene/util/IOUtils.java index 766d6fb32ea..350ae432306 100644 --- a/lucene/core/src/java/org/apache/lucene/util/IOUtils.java +++ b/lucene/core/src/java/org/apache/lucene/util/IOUtils.java @@ -113,20 +113,32 @@ public final class IOUtils { } /** - * Closes all given Closeables, suppressing all thrown exceptions. + * Closes all given Closeables, suppressing all thrown non {@link VirtualMachineError} exceptions. + * Even if a {@link VirtualMachineError} is thrown all given closeable are closed. * @see #closeWhileHandlingException(Closeable...) */ public static void closeWhileHandlingException(Iterable objects) { + VirtualMachineError firstError = null; + Throwable firstThrowable = null; for (Closeable object : objects) { try { if (object != null) { object.close(); } } catch (VirtualMachineError e) { - throw e; + firstError = useOrSuppress(firstError, e); } catch (Throwable t) { + firstThrowable = useOrSuppress(firstThrowable, t); } } + if (firstError != null) { + // we ensure that we bubble up any errors. We can't recover from these but need to make sure they are + // bubbled up. if a non-VMError is thrown we also add the suppressed exceptions to it. + if (firstThrowable != null) { + firstError.addSuppressed(firstThrowable); + } + throw firstError; + } } /** adds a Throwable to the list of suppressed Exceptions of the first Throwable