EndPoint onIdleExpired should not close on its own

+ From discussion with Simone, the dispatched fillInterest.onFail()
  needs to occur, so that the AbstractConnection.onReadTimeout() can
  handle the close conditions needed by SPDY and WebSocket.
  The EndPoint close within onIdleExpired is a race condition with
  this onReadTimeout desired behavior.
diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractEndPoint.java b/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractEndPoint.java
index 6517dbd..bfcb1aa 100644
--- a/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractEndPoint.java
+++ b/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractEndPoint.java
@@ -142,12 +142,9 @@
     @Override
     protected void onIdleExpired(TimeoutException timeout)
     {
-        boolean output_shutdown=isOutputShutdown();
-        boolean input_shutdown=isInputShutdown();
+        // Note: Rely on fillInterest to notify onReadTimeout to close connection.
         _fillInterest.onFail(timeout);
         _writeFlusher.onFail(timeout);
-        if (isOpen() && output_shutdown || input_shutdown)
-            close();
     }
 
     @Override
diff --git a/jetty-io/src/test/java/org/eclipse/jetty/io/ByteArrayEndPointTest.java b/jetty-io/src/test/java/org/eclipse/jetty/io/ByteArrayEndPointTest.java
index 1db6908..d23be98 100644
--- a/jetty-io/src/test/java/org/eclipse/jetty/io/ByteArrayEndPointTest.java
+++ b/jetty-io/src/test/java/org/eclipse/jetty/io/ByteArrayEndPointTest.java
@@ -18,6 +18,7 @@
 
 package org.eclipse.jetty.io;
 
+import static org.hamcrest.Matchers.*;
 import static org.hamcrest.Matchers.containsString;
 import static org.hamcrest.Matchers.greaterThan;
 import static org.hamcrest.Matchers.instanceOf;
@@ -36,6 +37,8 @@
 import org.eclipse.jetty.toolchain.test.annotation.Slow;
 import org.eclipse.jetty.util.BufferUtil;
 import org.eclipse.jetty.util.FutureCallback;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
 import org.eclipse.jetty.util.thread.Scheduler;
 import org.eclipse.jetty.util.thread.TimerScheduler;
 import org.junit.After;
@@ -235,6 +238,26 @@
         assertEquals(null, fcb.get());
         assertEquals(" more.", endp.getOutputString());
     }
+    
+    /**
+     * Simulate AbstractConnection.ReadCallback.failed()
+     */
+    public static class Closer extends FutureCallback
+    {
+        private EndPoint endp;
+
+        public Closer(EndPoint endp)
+        {
+            this.endp = endp;
+        }
+
+        @Override
+        public void failed(Throwable cause)
+        {
+            endp.close();
+            super.failed(cause);
+        }
+    }
 
     @Slow
     @Test
@@ -275,7 +298,7 @@
             assertThat(t.getCause(), instanceOf(TimeoutException.class));
         }
         assertThat(System.currentTimeMillis() - start, greaterThan(idleTimeout / 2));
-        assertTrue(endp.isOpen());
+        assertThat("Endpoint open", endp.isOpen(), is(true));
 
         // We need to delay the write timeout test below from the read timeout test above.
         // The reason is that the scheduler thread that fails the endPoint WriteFlusher
@@ -298,17 +321,19 @@
             assertThat(t.getCause(), instanceOf(TimeoutException.class));
         }
         assertThat(System.currentTimeMillis() - start, greaterThan(idleTimeout / 2));
-        assertTrue(endp.isOpen());
+        assertThat("Endpoint open", endp.isOpen(), is(true));
 
-        // Still no idle close
-        Thread.sleep(idleTimeout * 2);
-        assertTrue(endp.isOpen());
+        endp.fillInterested(new Closer(endp));
+        
+        // Still no idle close (wait half the time)
+        Thread.sleep(idleTimeout / 2);
+        assertThat("Endpoint open", endp.isOpen(), is(true));
 
         // shutdown out
         endp.shutdownOutput();
 
-        // idle close
+        // idle close (wait double the time)
         Thread.sleep(idleTimeout * 2);
-        assertFalse(endp.isOpen());
+        assertThat("Endpoint open", endp.isOpen(), is(false));
     }
 }