Index: lucene/src/java/org/apache/lucene/search/NRTManagerReopenThread.java =================================================================== --- lucene/src/java/org/apache/lucene/search/NRTManagerReopenThread.java (revision 1201313) +++ lucene/src/java/org/apache/lucene/search/NRTManagerReopenThread.java (working copy) @@ -20,6 +20,7 @@ import java.io.Closeable; import java.io.IOException; +import org.apache.lucene.util.IOUtils; import org.apache.lucene.util.ThreadInterruptedException; /** @@ -192,6 +193,7 @@ } } } catch (Throwable t) { + IOUtils.maybeRestoreInterrupt(t); //System.out.println("REOPEN EXC"); //t.printStackTrace(System.out); throw new RuntimeException(t); Index: lucene/src/java/org/apache/lucene/index/SegmentNorms.java =================================================================== --- lucene/src/java/org/apache/lucene/index/SegmentNorms.java (revision 1201313) +++ lucene/src/java/org/apache/lucene/index/SegmentNorms.java (working copy) @@ -24,6 +24,7 @@ import org.apache.lucene.store.IOContext; import org.apache.lucene.store.IndexInput; import org.apache.lucene.store.IndexOutput; +import org.apache.lucene.util.IOUtils; /** * Byte[] referencing is used because a new norm object needs * to be created for each clone, and the byte array is all @@ -235,6 +236,7 @@ try { owner.directory().deleteFile(normFileName); } catch (Throwable t) { + IOUtils.maybeRestoreInterrupt(t); // suppress this so we keep throwing the // original exception } Index: lucene/src/java/org/apache/lucene/index/DocumentsWriterPerThread.java =================================================================== --- lucene/src/java/org/apache/lucene/index/DocumentsWriterPerThread.java (revision 1201313) +++ lucene/src/java/org/apache/lucene/index/DocumentsWriterPerThread.java (working copy) @@ -33,6 +33,7 @@ import org.apache.lucene.store.IOContext; import org.apache.lucene.util.BitVector; import org.apache.lucene.util.Counter; +import org.apache.lucene.util.IOUtils; import org.apache.lucene.util.ByteBlockPool.Allocator; import org.apache.lucene.util.ByteBlockPool.DirectTrackingAllocator; import org.apache.lucene.util.InfoStream; @@ -137,6 +138,7 @@ try { consumer.abort(); } catch (Throwable t) { + IOUtils.maybeRestoreInterrupt(t); } pendingDeletes.clear(); Index: lucene/src/java/org/apache/lucene/index/SegmentInfo.java =================================================================== --- lucene/src/java/org/apache/lucene/index/SegmentInfo.java (revision 1201313) +++ lucene/src/java/org/apache/lucene/index/SegmentInfo.java (working copy) @@ -35,6 +35,7 @@ import org.apache.lucene.store.IndexInput; import org.apache.lucene.store.IndexOutput; import org.apache.lucene.util.Constants; +import org.apache.lucene.util.IOUtils; import org.apache.lucene.util.StringHelper; /** @@ -722,6 +723,7 @@ s.append('v'); } } catch (Throwable e) { + IOUtils.maybeRestoreInterrupt(e); // Messy: because getHasVectors may be used in an // thread-unsafe way, and may attempt to open an fnm // file that has since (legitimately) been deleted by Index: lucene/src/java/org/apache/lucene/index/SegmentReader.java =================================================================== --- lucene/src/java/org/apache/lucene/index/SegmentReader.java (revision 1201313) +++ lucene/src/java/org/apache/lucene/index/SegmentReader.java (working copy) @@ -37,6 +37,7 @@ import org.apache.lucene.util.Bits; import org.apache.lucene.util.BytesRef; import org.apache.lucene.util.CloseableThreadLocal; +import org.apache.lucene.util.IOUtils; import org.apache.lucene.util.StringHelper; /** @@ -343,6 +344,7 @@ try { directory().deleteFile(delFileName); } catch (Throwable t) { + IOUtils.maybeRestoreInterrupt(t); // suppress this so we keep throwing the // original exception } Index: lucene/src/java/org/apache/lucene/index/SegmentInfos.java =================================================================== --- lucene/src/java/org/apache/lucene/index/SegmentInfos.java (revision 1201313) +++ lucene/src/java/org/apache/lucene/index/SegmentInfos.java (working copy) @@ -346,6 +346,7 @@ directory.deleteFile(segmentFileName); } catch (Throwable t) { // Suppress so we keep throwing the original exception + IOUtils.maybeRestoreInterrupt(t); } if (globalFieldMapFile != null) { // delete if written here try { @@ -354,6 +355,7 @@ directory.deleteFile(globalFieldMapFile); } catch (Throwable t) { // Suppress so we keep throwing the original exception + IOUtils.maybeRestoreInterrupt(t); } } pendingMapVersion = -1; @@ -776,6 +778,7 @@ try { pendingSegnOutput.close(); } catch (Throwable t) { + IOUtils.maybeRestoreInterrupt(t); // Suppress so we keep throwing the original exception // in our caller } @@ -788,6 +791,7 @@ generation); dir.deleteFile(segmentFileName); } catch (Throwable t) { + IOUtils.maybeRestoreInterrupt(t); // Suppress so we keep throwing the original exception // in our caller } @@ -797,6 +801,7 @@ final String fieldMapName = getGlobalFieldNumberName(globalFieldMapVersion--); dir.deleteFile(fieldMapName); } catch (Throwable t) { + IOUtils.maybeRestoreInterrupt(t); // Suppress so we keep throwing the original exception // in our caller } @@ -832,12 +837,14 @@ try { output.close(); } catch (Throwable t) { + IOUtils.maybeRestoreInterrupt(t); // throw orig excp } if (!success) { try { dir.deleteFile(name); } catch (Throwable t) { + IOUtils.maybeRestoreInterrupt(t); // throw orig excp } } else { @@ -923,6 +930,7 @@ try { dir.deleteFile(fileName); } catch (Throwable t) { + IOUtils.maybeRestoreInterrupt(t); // Suppress so we keep throwing the original exception } } Index: lucene/src/java/org/apache/lucene/index/DirectoryReader.java =================================================================== --- lucene/src/java/org/apache/lucene/index/DirectoryReader.java (revision 1201313) +++ lucene/src/java/org/apache/lucene/index/DirectoryReader.java (working copy) @@ -36,6 +36,7 @@ import org.apache.lucene.index.codecs.PerDocValues; import org.apache.lucene.util.Bits; import org.apache.lucene.util.BytesRef; +import org.apache.lucene.util.IOUtils; import org.apache.lucene.util.MapBackedSet; /** @@ -120,6 +121,7 @@ try { readers[i].close(); } catch (Throwable ignore) { + IOUtils.maybeRestoreInterrupt(ignore); // keep going - we want to clean up as much as possible } } @@ -171,6 +173,7 @@ try { reader.close(); } catch (Throwable ignore) { + IOUtils.maybeRestoreInterrupt(ignore); // keep going - we want to clean up as much as possible } } Index: lucene/src/java/org/apache/lucene/index/DocFieldProcessor.java =================================================================== --- lucene/src/java/org/apache/lucene/index/DocFieldProcessor.java (revision 1201313) +++ lucene/src/java/org/apache/lucene/index/DocFieldProcessor.java (working copy) @@ -100,6 +100,7 @@ try { field.abort(); } catch (Throwable t) { + IOUtils.maybeRestoreInterrupt(t); if (th == null) { th = t; } @@ -111,12 +112,14 @@ IOUtils.closeWhileHandlingException(perDocConsumers.values()); // TODO add abort to PerDocConsumer! } catch (IOException e) { + IOUtils.maybeRestoreInterrupt(e); // ignore on abort! } try { fieldsWriter.abort(); } catch (Throwable t) { + IOUtils.maybeRestoreInterrupt(t); if (th == null) { th = t; } @@ -125,6 +128,7 @@ try { consumer.abort(); } catch (Throwable t) { + IOUtils.maybeRestoreInterrupt(t); if (th == null) { th = t; } Index: lucene/src/java/org/apache/lucene/index/IndexWriter.java =================================================================== --- lucene/src/java/org/apache/lucene/index/IndexWriter.java (revision 1201313) +++ lucene/src/java/org/apache/lucene/index/IndexWriter.java (working copy) @@ -916,6 +916,7 @@ try { writeLock.release(); } catch (Throwable t) { + IOUtils.maybeRestoreInterrupt(t); // don't mask the original exception } writeLock = null; @@ -2232,6 +2233,7 @@ try { directory.deleteFile(delFileName); } catch (Throwable t) { + IOUtils.maybeRestoreInterrupt(t); // suppress this so we keep throwing the // original exception } @@ -3166,7 +3168,7 @@ } final private void handleMergeException(Throwable t, MergePolicy.OneMerge merge) throws IOException { - + IOUtils.maybeRestoreInterrupt(t); if (infoStream != null) { infoStream.message("IW", "handleMergeException: merge=" + merge.segString(directory) + " exc=" + t); } @@ -3483,6 +3485,7 @@ anyChanges |= readerPool.release(merge.readers.get(i), drop, IOContext.Context.MERGE); } catch (Throwable t) { if (th == null) { + IOUtils.maybeRestoreInterrupt(t); th = t; } } Index: lucene/src/java/org/apache/lucene/messages/NLS.java =================================================================== --- lucene/src/java/org/apache/lucene/messages/NLS.java (revision 1201313) +++ lucene/src/java/org/apache/lucene/messages/NLS.java (working copy) @@ -29,6 +29,8 @@ import java.util.MissingResourceException; import java.util.ResourceBundle; +import org.apache.lucene.util.IOUtils; + /** * MessageBundles classes extend this class, to implement a bundle. * @@ -95,6 +97,7 @@ if (!bundles.containsKey(bundleName)) bundles.put(bundleName, clazz); } catch (Throwable e) { + IOUtils.maybeRestoreInterrupt(e); // ignore all errors and exceptions // because this function is supposed to be called at class load time. } @@ -182,6 +185,7 @@ System.err.println("WARN: Message with key:" + key + " and locale: " + Locale.getDefault() + " not found."); } catch (Throwable e) { + IOUtils.maybeRestoreInterrupt(e); // ignore all other errors and exceptions // since this code is just a test to see if the message is present on the // system Index: lucene/src/java/org/apache/lucene/store/FSDirectory.java =================================================================== --- lucene/src/java/org/apache/lucene/store/FSDirectory.java (revision 1201313) +++ lucene/src/java/org/apache/lucene/store/FSDirectory.java (working copy) @@ -29,6 +29,7 @@ import java.util.Set; import java.util.concurrent.Future; +import org.apache.lucene.util.IOUtils; import org.apache.lucene.util.ThreadInterruptedException; import org.apache.lucene.util.Constants; @@ -484,6 +485,7 @@ try { file.close(); } catch (Throwable t) { + IOUtils.maybeRestoreInterrupt(t); // Suppress so we don't mask original exception } } else { Index: lucene/src/java/org/apache/lucene/util/IOUtils.java =================================================================== --- lucene/src/java/org/apache/lucene/util/IOUtils.java (revision 1201313) +++ lucene/src/java/org/apache/lucene/util/IOUtils.java (working copy) @@ -81,18 +81,12 @@ addSuppressed((priorException == null) ? th : priorException, t); if (th == null) { th = t; + } else { + maybeRestoreInterrupt(t); } } } - - if (priorException != null) { - throw priorException; - } else if (th != null) { - if (th instanceof IOException) throw (IOException) th; - if (th instanceof RuntimeException) throw (RuntimeException) th; - if (th instanceof Error) throw (Error) th; - throw new RuntimeException(th); - } + handleException(priorException, th); } /** @see #closeWhileHandlingException(Exception, Closeable...) */ @@ -108,18 +102,14 @@ addSuppressed((priorException == null) ? th : priorException, t); if (th == null) { th = t; + } else { + // only if we don't rethrow + maybeRestoreInterrupt(t); } } } - if (priorException != null) { - throw priorException; - } else if (th != null) { - if (th instanceof IOException) throw (IOException) th; - if (th instanceof RuntimeException) throw (RuntimeException) th; - if (th instanceof Error) throw (Error) th; - throw new RuntimeException(th); - } + handleException(priorException, th); } /** @@ -144,16 +134,13 @@ addSuppressed(th, t); if (th == null) { th = t; + } else { + maybeRestoreInterrupt(t); } } } - if (th != null) { - if (th instanceof IOException) throw (IOException) th; - if (th instanceof RuntimeException) throw (RuntimeException) th; - if (th instanceof Error) throw (Error) th; - throw new RuntimeException(th); - } + handleException(th); } /** @@ -171,16 +158,12 @@ addSuppressed(th, t); if (th == null) { th = t; + } else { + maybeRestoreInterrupt(t); } } } - - if (th != null) { - if (th instanceof IOException) throw (IOException) th; - if (th instanceof RuntimeException) throw (RuntimeException) th; - if (th instanceof Error) throw (Error) th; - throw new RuntimeException(th); - } + handleException(th); } /** @@ -197,6 +180,7 @@ object.close(); } } catch (Throwable t) { + maybeRestoreInterrupt(t); } } } @@ -211,10 +195,45 @@ object.close(); } } catch (Throwable t) { + maybeRestoreInterrupt(t); } } } + private static void handleException(Throwable th) throws IOException { + if (th != null) { + if (th instanceof IOException) throw (IOException) th; + if (th instanceof RuntimeException) throw (RuntimeException) th; + if (th instanceof Error) throw (Error) th; + maybeRestoreInterrupt(th); // now check interrupt since we wrap in RuntimeExcp. + throw new RuntimeException(th); + } + } + private static void handleException(E priorException, Throwable th) throws E, IOException { + if (priorException != null) { + maybeRestoreInterrupt(th); + throw priorException; + } else { + handleException(th); + } + } + + /** + * Restores the interrupt bit on the current thread iff one of the given exceptions is a + * {@link InterruptedException} or a {@link ThreadInterruptedException}. + * @param th exceptions to check + */ + public static void maybeRestoreInterrupt(Throwable... th) { + for (int i = 0; i < th.length; i++) { + if (th[i] != null) { + if ((th[i] instanceof InterruptedException) || (th[i] instanceof ThreadInterruptedException)) { + Thread.currentThread().interrupt(); + return; + } + } + } + } + /** This reflected {@link Method} is {@code null} before Java 7 */ private static final Method SUPPRESS_METHOD; static { Index: lucene/src/java/org/apache/lucene/util/TwoPhaseCommitTool.java =================================================================== --- lucene/src/java/org/apache/lucene/util/TwoPhaseCommitTool.java (revision 1201313) +++ lucene/src/java/org/apache/lucene/util/TwoPhaseCommitTool.java (working copy) @@ -99,7 +99,9 @@ if (tpc != null) { try { tpc.rollback(); - } catch (Throwable t) {} + } catch (Throwable t) { + IOUtils.maybeRestoreInterrupt(t); + } } } } @@ -137,6 +139,7 @@ } } } catch (Throwable t) { + IOUtils.maybeRestoreInterrupt(t); // first object that fails results in rollback all of them and // throwing an exception. rollback(objects); @@ -152,6 +155,7 @@ } } } catch (Throwable t) { + IOUtils.maybeRestoreInterrupt(t); // first object that fails results in rollback all of them and // throwing an exception. rollback(objects);