Index: CHANGES.txt =================================================================== --- CHANGES.txt (revision 835808) +++ CHANGES.txt (working copy) @@ -16,6 +16,14 @@ the internal cache implementation for thread safety, before it was declared protected. (Peter Lenahan, Uwe Schindler, Simon Willnauer) +* LUCENE-2053: If you call Thread.interrupt() on a thread inside + Lucene, Lucene will do its best to interrupt the thread. However, + instead of throwing InterruptedException (which is a checked + exception), you'll get an oal.util.ThreadInterruptedException (an + unchecked exception, subclassing RuntimeException). The interrupt + status on the thread is cleared when this exception is thrown. + (Mike McCandless) + Changes in runtime behavior * LUCENE-1677: Remove the system property to set SegmentReader class Index: src/test/org/apache/lucene/TestSnapshotDeletionPolicy.java =================================================================== --- src/test/org/apache/lucene/TestSnapshotDeletionPolicy.java (revision 835808) +++ src/test/org/apache/lucene/TestSnapshotDeletionPolicy.java (working copy) @@ -36,7 +36,7 @@ import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.TestIndexWriter; import org.apache.lucene.index.SnapshotDeletionPolicy; - +import org.apache.lucene.util.ThreadInterruptedException; import org.apache.lucene.util.LuceneTestCase; import org.apache.lucene.util._TestUtil; @@ -141,8 +141,7 @@ try { Thread.sleep(1); } catch (InterruptedException ie) { - Thread.currentThread().interrupt(); - throw new RuntimeException(ie); + throw new ThreadInterruptedException(ie); } } } Index: src/test/org/apache/lucene/search/TestTimeLimitingCollector.java =================================================================== --- src/test/org/apache/lucene/search/TestTimeLimitingCollector.java (revision 835808) +++ src/test/org/apache/lucene/search/TestTimeLimitingCollector.java (working copy) @@ -32,6 +32,7 @@ import org.apache.lucene.store.RAMDirectory; import org.apache.lucene.util.LuceneTestCase; import org.apache.lucene.util.Version; +import org.apache.lucene.util.ThreadInterruptedException; /** * Tests the {@link TimeLimitingCollector}. This test checks (1) search @@ -328,8 +329,7 @@ try { Thread.sleep(slowdown); } catch (InterruptedException ie) { - Thread.currentThread().interrupt(); - throw new RuntimeException(ie); + throw new ThreadInterruptedException(ie); } } assert docId >= 0: " base=" + docBase + " doc=" + doc; Index: src/test/org/apache/lucene/index/TestIndexWriter.java =================================================================== --- src/test/org/apache/lucene/index/TestIndexWriter.java (revision 835808) +++ src/test/org/apache/lucene/index/TestIndexWriter.java (working copy) @@ -66,6 +66,7 @@ import org.apache.lucene.util.UnicodeUtil; import org.apache.lucene.util._TestUtil; import org.apache.lucene.util.Version; +import org.apache.lucene.util.ThreadInterruptedException; public class TestIndexWriter extends LuceneTestCase { public TestIndexWriter(String name) { @@ -2216,8 +2217,7 @@ try { Thread.sleep(1); } catch (InterruptedException ie) { - Thread.currentThread().interrupt(); - throw new RuntimeException(ie); + throw new ThreadInterruptedException(ie); } if (fullCount++ >= 5) break; @@ -4385,18 +4385,13 @@ w.addDocument(doc); w.commit(); } - } catch (RuntimeException re) { + } catch (ThreadInterruptedException re) { Throwable e = re.getCause(); - if (e instanceof InterruptedException) { - // Make sure IW restored interrupted bit - if (!interrupted()) { - System.out.println("FAILED; InterruptedException hit but thread.interrupted() was false"); - e.printStackTrace(System.out); - failed = true; - break; - } - } else { - System.out.println("FAILED; unexpected exception"); + assertTrue(e instanceof InterruptedException); + + // Make sure IW cleared the interrupted bit + if (interrupted()) { + System.out.println("FAILED; InterruptedException hit but thread.interrupted() was true"); e.printStackTrace(System.out); failed = true; break; Index: src/test/org/apache/lucene/index/TestIndexWriterReader.java =================================================================== --- src/test/org/apache/lucene/index/TestIndexWriterReader.java (revision 835808) +++ src/test/org/apache/lucene/index/TestIndexWriterReader.java (working copy) @@ -38,6 +38,7 @@ import org.apache.lucene.store.AlreadyClosedException; import org.apache.lucene.util.LuceneTestCase; import org.apache.lucene.util._TestUtil; +import org.apache.lucene.util.ThreadInterruptedException; public class TestIndexWriterReader extends LuceneTestCase { static PrintStream infoStream; @@ -360,7 +361,7 @@ try { threads[i].join(); } catch (InterruptedException ie) { - Thread.currentThread().interrupt(); + throw new ThreadInterruptedException(ie); } } } @@ -402,7 +403,7 @@ try { threads[i].join(); } catch (InterruptedException ie) { - Thread.currentThread().interrupt(); + throw new ThreadInterruptedException(ie); } } Index: src/java/org/apache/lucene/search/FilterManager.java =================================================================== --- src/java/org/apache/lucene/search/FilterManager.java (revision 835808) +++ src/java/org/apache/lucene/search/FilterManager.java (working copy) @@ -24,6 +24,8 @@ import java.util.Map; import java.util.TreeSet; +import org.apache.lucene.util.ThreadInterruptedException; + /** * Filter caching singleton. It can be used * to save filters locally for reuse. @@ -193,8 +195,7 @@ try { Thread.sleep(cleanSleepTime); } catch (InterruptedException ie) { - Thread.currentThread().interrupt(); - throw new RuntimeException(ie); + throw new ThreadInterruptedException(ie); } } } Index: src/java/org/apache/lucene/search/TimeLimitingCollector.java =================================================================== --- src/java/org/apache/lucene/search/TimeLimitingCollector.java (revision 835808) +++ src/java/org/apache/lucene/search/TimeLimitingCollector.java (working copy) @@ -20,6 +20,7 @@ import java.io.IOException; import org.apache.lucene.index.IndexReader; +import org.apache.lucene.util.ThreadInterruptedException; /** * The {@link TimeLimitingCollector} is used to timeout search requests that @@ -78,8 +79,7 @@ try { Thread.sleep( resolution ); } catch (InterruptedException ie) { - Thread.currentThread().interrupt(); - throw new RuntimeException(ie); + throw new ThreadInterruptedException(ie); } } } Index: src/java/org/apache/lucene/search/ParallelMultiSearcher.java =================================================================== --- src/java/org/apache/lucene/search/ParallelMultiSearcher.java (revision 835808) +++ src/java/org/apache/lucene/search/ParallelMultiSearcher.java (working copy) @@ -33,6 +33,7 @@ import org.apache.lucene.index.Term; import org.apache.lucene.util.NamedThreadFactory; import org.apache.lucene.util.PriorityQueue; +import org.apache.lucene.util.ThreadInterruptedException; /** Implements parallel search over a set of Searchables. * @@ -186,11 +187,8 @@ if (e.getCause() instanceof IOException) throw (IOException) e.getCause(); throw new RuntimeException(e.getCause()); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - // In 3.0 we will change this to throw - // InterruptedException instead - throw new RuntimeException(e); + } catch (InterruptedException ie) { + throw new ThreadInterruptedException(ie); } } } Index: src/java/org/apache/lucene/index/SegmentInfos.java =================================================================== --- src/java/org/apache/lucene/index/SegmentInfos.java (revision 835808) +++ src/java/org/apache/lucene/index/SegmentInfos.java (working copy) @@ -23,6 +23,7 @@ import org.apache.lucene.store.ChecksumIndexOutput; import org.apache.lucene.store.ChecksumIndexInput; import org.apache.lucene.store.NoSuchDirectoryException; +import org.apache.lucene.util.ThreadInterruptedException; import java.io.FileNotFoundException; import java.io.IOException; @@ -610,10 +611,7 @@ try { Thread.sleep(defaultGenFileRetryPauseMsec); } catch (InterruptedException ie) { - // In 3.0 we will change this to throw - // InterruptedException instead - Thread.currentThread().interrupt(); - throw new RuntimeException(ie); + throw new ThreadInterruptedException(ie); } } Index: src/java/org/apache/lucene/index/ConcurrentMergeScheduler.java =================================================================== --- src/java/org/apache/lucene/index/ConcurrentMergeScheduler.java (revision 835808) +++ src/java/org/apache/lucene/index/ConcurrentMergeScheduler.java (working copy) @@ -18,6 +18,7 @@ */ import org.apache.lucene.store.Directory; +import org.apache.lucene.util.ThreadInterruptedException; import java.io.IOException; import java.util.List; @@ -130,10 +131,7 @@ try { wait(); } catch (InterruptedException ie) { - // In 3.0 we will change this to throw - // InterruptedException instead - Thread.currentThread().interrupt(); - throw new RuntimeException(ie); + throw new ThreadInterruptedException(ie); } } } @@ -200,10 +198,7 @@ try { wait(); } catch (InterruptedException ie) { - // In 3.0 we will change this to throw - // InterruptedException instead - Thread.currentThread().interrupt(); - throw new RuntimeException(ie); + throw new ThreadInterruptedException(ie); } } @@ -347,9 +342,7 @@ // cases: Thread.sleep(250); } catch (InterruptedException ie) { - Thread.currentThread().interrupt(); - // In 3.0 this will throw InterruptedException - throw new RuntimeException(ie); + throw new ThreadInterruptedException(ie); } throw new MergePolicy.MergeException(exc, dir); } Index: src/java/org/apache/lucene/index/DocumentsWriter.java =================================================================== --- src/java/org/apache/lucene/index/DocumentsWriter.java (revision 835808) +++ src/java/org/apache/lucene/index/DocumentsWriter.java (working copy) @@ -38,6 +38,7 @@ import org.apache.lucene.store.Directory; import org.apache.lucene.util.ArrayUtil; import org.apache.lucene.util.Constants; +import org.apache.lucene.util.ThreadInterruptedException; /** * This class accepts multiple added documents and directly @@ -513,10 +514,7 @@ try { wait(); } catch (InterruptedException ie) { - // In 3.0 we will change this to throw - // InterruptedException instead - Thread.currentThread().interrupt(); - throw new RuntimeException(ie); + throw new ThreadInterruptedException(ie); } } @@ -851,10 +849,7 @@ try { wait(); } catch (InterruptedException ie) { - // In 3.0 we will change this to throw - // InterruptedException instead - Thread.currentThread().interrupt(); - throw new RuntimeException(ie); + throw new ThreadInterruptedException(ie); } } @@ -1108,10 +1103,7 @@ try { wait(); } catch (InterruptedException ie) { - // In 3.0 we will change this to throw - // InterruptedException instead - Thread.currentThread().interrupt(); - throw new RuntimeException(ie); + throw new ThreadInterruptedException(ie); } } while (!waitQueue.doResume()); } Index: src/java/org/apache/lucene/index/IndexWriter.java =================================================================== --- src/java/org/apache/lucene/index/IndexWriter.java (revision 835808) +++ src/java/org/apache/lucene/index/IndexWriter.java (working copy) @@ -28,6 +28,7 @@ import org.apache.lucene.store.AlreadyClosedException; import org.apache.lucene.store.BufferedIndexInput; import org.apache.lucene.util.Constants; +import org.apache.lucene.util.ThreadInterruptedException; import java.io.IOException; import java.io.Closeable; @@ -144,6 +145,13 @@ synchronize on the IndexWriter instance as this may cause deadlock; use your own (non-Lucene) objects instead.

+ +

NOTE: If you call + Thread.interrupt() on a thread that's within + IndexWriter, IndexWriter will try to catch this (eg, if + it's in a wait() or Thread.sleep()), and will then throw + the unchecked exception {@link ThreadInterruptedException} + and clear the interrupt status on the thread.

*/ /* @@ -4506,10 +4514,7 @@ try { synced.wait(); } catch (InterruptedException ie) { - // In 3.0 we will change this to throw - // InterruptedException instead - Thread.currentThread().interrupt(); - throw new RuntimeException(ie); + throw new ThreadInterruptedException(ie); } } } @@ -4527,10 +4532,7 @@ try { wait(1000); } catch (InterruptedException ie) { - // In 3.0 we will change this to throw - // InterruptedException instead - Thread.currentThread().interrupt(); - throw new RuntimeException(ie); + throw new ThreadInterruptedException(ie); } } Index: src/java/org/apache/lucene/store/Lock.java =================================================================== --- src/java/org/apache/lucene/store/Lock.java (revision 835808) +++ src/java/org/apache/lucene/store/Lock.java (working copy) @@ -17,6 +17,7 @@ * limitations under the License. */ +import org.apache.lucene.util.ThreadInterruptedException; import java.io.IOException; /** An interprocess mutex lock. @@ -88,11 +89,8 @@ } try { Thread.sleep(LOCK_POLL_INTERVAL); - } catch (InterruptedException e) { - // In 3.0 we will change this to throw - // InterruptedException instead - Thread.currentThread().interrupt(); - throw new IOException(e.toString()); + } catch (InterruptedException ie) { + throw new ThreadInterruptedException(ie); } locked = obtain(); } Index: src/java/org/apache/lucene/store/RAMDirectory.java =================================================================== --- src/java/org/apache/lucene/store/RAMDirectory.java (revision 835808) +++ src/java/org/apache/lucene/store/RAMDirectory.java (working copy) @@ -22,6 +22,7 @@ import java.io.Serializable; import java.util.HashMap; import java.util.Set; +import org.apache.lucene.util.ThreadInterruptedException; /** * A memory-resident {@link Directory} implementation. Locking @@ -124,10 +125,7 @@ try { Thread.sleep(0, 1); } catch (InterruptedException ie) { - // In 3.0 we will change this to throw - // InterruptedException instead - Thread.currentThread().interrupt(); - throw new RuntimeException(ie); + throw new ThreadInterruptedException(ie); } ts2 = System.currentTimeMillis(); } while(ts1 == ts2); Index: src/java/org/apache/lucene/store/FSDirectory.java =================================================================== --- src/java/org/apache/lucene/store/FSDirectory.java (revision 835808) +++ src/java/org/apache/lucene/store/FSDirectory.java (working copy) @@ -24,6 +24,7 @@ import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import org.apache.lucene.util.ThreadInterruptedException; import org.apache.lucene.util.Constants; /** @@ -317,10 +318,7 @@ // Pause 5 msec Thread.sleep(5); } catch (InterruptedException ie) { - // In 3.0 we will change this to throw - // InterruptedException instead - Thread.currentThread().interrupt(); - throw new RuntimeException(ie); + throw new ThreadInterruptedException(ie); } } } Index: src/java/org/apache/lucene/util/ThreadInterruptedException.java =================================================================== --- src/java/org/apache/lucene/util/ThreadInterruptedException.java (revision 0) +++ src/java/org/apache/lucene/util/ThreadInterruptedException.java (revision 0) @@ -0,0 +1,30 @@ +package org.apache.lucene.util; + +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Thrown by lucene on detecting that Thread.interrupt() had + * been called. Unlike Java's InterruptedException, this + * exception is not checked.. + */ + +public final class ThreadInterruptedException extends RuntimeException { + public ThreadInterruptedException(InterruptedException ie) { + super(ie); + } +} Property changes on: src/java/org/apache/lucene/util/ThreadInterruptedException.java ___________________________________________________________________ Added: svn:eol-style + native Index: contrib/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/NearRealtimeReaderTask.java =================================================================== --- contrib/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/NearRealtimeReaderTask.java (revision 835808) +++ contrib/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/NearRealtimeReaderTask.java (working copy) @@ -29,6 +29,7 @@ import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.TopFieldDocs; import org.apache.lucene.index.Term; +import org.apache.lucene.util.ThreadInterruptedException; /** * Spawns a BG thread that periodically (defaults to 3.0 @@ -93,7 +94,7 @@ try { Thread.sleep(delay); } catch (InterruptedException ie) { - throw new RuntimeException(ie); + throw new ThreadInterruptedException(ie); } } } Index: contrib/benchmark/src/java/org/apache/lucene/benchmark/byTask/feeds/EnwikiContentSource.java =================================================================== --- contrib/benchmark/src/java/org/apache/lucene/benchmark/byTask/feeds/EnwikiContentSource.java (revision 835808) +++ contrib/benchmark/src/java/org/apache/lucene/benchmark/byTask/feeds/EnwikiContentSource.java (working copy) @@ -24,6 +24,7 @@ import java.util.Map; import org.apache.lucene.benchmark.byTask.utils.Config; +import org.apache.lucene.util.ThreadInterruptedException; import org.xml.sax.Attributes; import org.xml.sax.InputSource; import org.xml.sax.SAXException; @@ -66,6 +67,7 @@ try { wait(); } catch (InterruptedException ie) { + throw new ThreadInterruptedException(ie); } } if (nmde != null) { @@ -127,6 +129,7 @@ try { wait(); } catch (InterruptedException ie) { + throw new ThreadInterruptedException(ie); } } tuple = tmpTuple; Index: contrib/benchmark/src/java/org/apache/lucene/benchmark/byTask/feeds/TrecContentSource.java =================================================================== --- contrib/benchmark/src/java/org/apache/lucene/benchmark/byTask/feeds/TrecContentSource.java (revision 835808) +++ contrib/benchmark/src/java/org/apache/lucene/benchmark/byTask/feeds/TrecContentSource.java (working copy) @@ -33,6 +33,7 @@ import org.apache.lucene.benchmark.byTask.utils.Config; import org.apache.lucene.benchmark.byTask.utils.StringBufferReader; +import org.apache.lucene.util.ThreadInterruptedException; /** * Implements a {@link ContentSource} over the TREC collection. @@ -302,10 +303,8 @@ try { docData = htmlParser.parse(docData, name, date, r, null); addDoc(); - } catch (InterruptedException e) { - IOException ex = new IOException(e.getMessage()); - ex.initCause(e); - throw ex; + } catch (InterruptedException ie) { + throw new ThreadInterruptedException(ie); } return docData; Index: tags/lucene_2_9_back_compat_tests_20091111/src/test/org/apache/lucene/index/TestIndexWriter.java =================================================================== --- tags/lucene_2_9_back_compat_tests_20091111/src/test/org/apache/lucene/index/TestIndexWriter.java (revision 835814) +++ tags/lucene_2_9_back_compat_tests_20091111/src/test/org/apache/lucene/index/TestIndexWriter.java (working copy) @@ -4366,16 +4366,11 @@ } } catch (RuntimeException re) { Throwable e = re.getCause(); - if (e instanceof InterruptedException) { - // Make sure IW restored interrupted bit - if (!interrupted()) { - System.out.println("FAILED; InterruptedException hit but thread.interrupted() was false"); - e.printStackTrace(System.out); - failed = true; - break; - } - } else { - System.out.println("FAILED; unexpected exception"); + assertTrue(e instanceof InterruptedException); + + // Make sure IW cleared the interrupted bit + if (interrupted()) { + System.out.println("FAILED; InterruptedException hit but thread.interrupted() was true"); e.printStackTrace(System.out); failed = true; break;