Author: ggregory Date: Thu Nov 22 00:36:10 2012 New Revision: 1412391 URL: http://svn.apache.org/viewvc?rev=1412391&view=rev Log: [IO-358][Tailer] InterruptedException while the thread is sleeping is silently ignored.
Modified: commons/proper/io/trunk/src/changes/changes.xml commons/proper/io/trunk/src/main/java/org/apache/commons/io/input/Tailer.java commons/proper/io/trunk/src/test/java/org/apache/commons/io/input/TailerTest.java Modified: commons/proper/io/trunk/src/changes/changes.xml URL: http://svn.apache.org/viewvc/commons/proper/io/trunk/src/changes/changes.xml?rev=1412391&r1=1412390&r2=1412391&view=diff ============================================================================== --- commons/proper/io/trunk/src/changes/changes.xml (original) +++ commons/proper/io/trunk/src/changes/changes.xml Thu Nov 22 00:36:10 2012 @@ -46,7 +46,10 @@ The <action> type attribute can be add,u <body> <!-- The release date is the date RC is cut --> - <release version="2.5" date="201?-??-??" description="New features and bug fixes."> + <release version="2.5" date="201?-??-??" description="New features and bug fixes."> + <action issue="IO-358" dev="ggregory" type="fix" due-to="mortenh"> + [Tailer] InterruptedException while the thead is sleeping is silently ignored + </action> <action issue="IO-353" dev="ggregory" type="add" due-to="ggregory"> Add API IOUtils.copy(InputStream, OutputStream, int) </action> Modified: commons/proper/io/trunk/src/main/java/org/apache/commons/io/input/Tailer.java URL: http://svn.apache.org/viewvc/commons/proper/io/trunk/src/main/java/org/apache/commons/io/input/Tailer.java?rev=1412391&r1=1412390&r2=1412391&view=diff ============================================================================== --- commons/proper/io/trunk/src/main/java/org/apache/commons/io/input/Tailer.java (original) +++ commons/proper/io/trunk/src/main/java/org/apache/commons/io/input/Tailer.java Thu Nov 22 00:36:10 2012 @@ -40,8 +40,7 @@ import org.apache.commons.io.IOUtils; * public void handle(String line) { * System.out.println(line); * } - * } - * </pre> + * }</pre> * * <h2>2. Using a Tailer</h2> * @@ -64,10 +63,9 @@ import org.apache.commons.io.IOUtils; * * <pre> * TailerListener listener = new MyTailerListener(); - * Tailer tailer = Tailer.create(file, listener, delay); - * </pre> + * Tailer tailer = Tailer.create(file, listener, delay);</pre> * - * <h3>2.2 Use an Executor</h3> + * <h3>2.2 Using an Executor</h3> * * <pre> * TailerListener listener = new MyTailerListener(); @@ -84,25 +82,32 @@ import org.apache.commons.io.IOUtils; * </pre> * * - * <h3>2.3 Use a Thread</h3> + * <h3>2.3 Using a Thread</h3> * <pre> * TailerListener listener = new MyTailerListener(); * Tailer tailer = new Tailer(file, listener, delay); * Thread thread = new Thread(tailer); * thread.setDaemon(true); // optional - * thread.start(); - * </pre> + * thread.start();</pre> * - * <h2>3. Stop Tailing</h3> + * <h2>3. Stopping a Tailer</h3> * <p>Remember to stop the tailer when you have done with it:</p> * <pre> * tailer.stop(); * </pre> * + * <h2>4. Interrupting a Tailer</h3> + * <p>You can interrupt the thread a tailer is running on by calling {@link Thread#interrupt()}.</p> + * <pre> + * thread.interrupt(); + * </pre> + * <p>If you interrupt a tailer, the tailer listener is called with the {@link InterruptedException}.</p> + * * @see TailerListener * @see TailerListenerAdapter * @version $Id$ * @since 2.0 + * @since 2.5 Updated behavior and documentation for {@link Thread#interrupt()} */ public class Tailer implements Runnable { @@ -356,10 +361,7 @@ public class Tailer implements Runnable listener.fileNotFound(); } if (reader == null) { - try { - Thread.sleep(delayMillis); - } catch (InterruptedException e) { - } + Thread.sleep(delayMillis); } else { // The current position in the file position = end ? file.length() : 0; @@ -410,22 +412,27 @@ public class Tailer implements Runnable if (reOpen) { IOUtils.closeQuietly(reader); } - try { - Thread.sleep(delayMillis); - } catch (InterruptedException e) { - } + Thread.sleep(delayMillis); if (getRun() && reOpen) { reader = new RandomAccessFile(file, RAF_MODE); reader.seek(position); } } - } catch (Exception e) { - listener.handle(e); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + stop(e); + } catch (Exception e) { + stop(e); } finally { IOUtils.closeQuietly(reader); } } + private void stop(Exception e) { + listener.handle(e); + stop(); + } + /** * Allows the tailer to complete its current loop and return. */ Modified: commons/proper/io/trunk/src/test/java/org/apache/commons/io/input/TailerTest.java URL: http://svn.apache.org/viewvc/commons/proper/io/trunk/src/test/java/org/apache/commons/io/input/TailerTest.java?rev=1412391&r1=1412390&r2=1412391&view=diff ============================================================================== --- commons/proper/io/trunk/src/test/java/org/apache/commons/io/input/TailerTest.java (original) +++ commons/proper/io/trunk/src/test/java/org/apache/commons/io/input/TailerTest.java Thu Nov 22 00:36:10 2012 @@ -199,7 +199,8 @@ public class TailerTest extends FileBase Thread.sleep(testDelayMillis); write(file, "Line five"); assertEquals("4 line count", 0, listener.getLines().size()); - assertNull("Should not generate Exception", listener.exception); + assertNotNull("Missing InterruptedException", listener.exception); + assertTrue("Unexpected Exception: " + listener.exception, listener.exception instanceof InterruptedException); assertEquals("Expected init to be called", 1 , listener.initialised); assertEquals("fileNotFound should not be called", 0 , listener.notFound); assertEquals("fileRotated should be be called", 1 , listener.rotated); @@ -273,6 +274,33 @@ public class TailerTest extends FileBase assertEquals("fileRotated should be not be called", 0 , listener.rotated); } + /** + * Tests [IO-357][Tailer] InterruptedException while the thead is sleeping is silently ignored. + * + * @throws Exception + */ + public void testInterrupt() throws Exception { + final File file = new File(getTestDirectory(), "nosuchfile"); + assertFalse("nosuchfile should not exist", file.exists()); + final TestTailerListener listener = new TestTailerListener(); + // Use a long delay to try to make sure the test thread calls interrupt() while the tailer thread is sleeping. + int delay = 1000; + int idle = 50; // allow time for thread to work + Tailer tailer = new Tailer(file, listener, delay, false, 4096); + Thread thread = new Thread(tailer); + thread.setDaemon(true); + thread.start(); + Thread.sleep(idle); + thread.interrupt(); + tailer = null; + Thread.sleep(delay + idle); + assertNotNull("Missing InterruptedException", listener.exception); + assertTrue("Unexpected Exception: " + listener.exception, listener.exception instanceof InterruptedException); + assertEquals("Expected init to be called", 1, listener.initialised); + assertTrue("fileNotFound should be called", listener.notFound > 0); + assertEquals("fileRotated should be not be called", 0, listener.rotated); + } + public void testStopWithNoFileUsingExecutor() throws Exception { final File file = new File(getTestDirectory(),"nosuchfile"); assertFalse("nosuchfile should not exist", file.exists());