diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/AbstractGenerator.java b/jetty-http/src/main/java/org/eclipse/jetty/http/AbstractGenerator.java index 50f58ae63f1..6901fe1f63f 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/AbstractGenerator.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/AbstractGenerator.java @@ -483,8 +483,13 @@ public abstract class AbstractGenerator implements Generator { if (close) _persistent=false; - if (!isCommitted()) + if (isCommitted()) { + LOG.debug("sendError on committed: {} {}",code,reason); + } + else + { + LOG.debug("sendError: {} {}",code,reason); setResponse(code, reason); if (content != null) { diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncHttpConnection.java b/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncHttpConnection.java index b08315b84e0..e2a81e5de58 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncHttpConnection.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncHttpConnection.java @@ -27,7 +27,6 @@ public class AsyncHttpConnection extends HttpConnection public Connection handle() throws IOException { - LOG.debug("handle {}",this); Connection connection = this; boolean some_progress=false; boolean progress=true; @@ -60,6 +59,11 @@ public class AsyncHttpConnection extends HttpConnection // Flush output from buffering endpoint if (_endp.isBufferingOutput()) _endp.flush(); + + // Special case close handling. + // If we were dispatched and have made no progress, but io is shutdown, then close + if (!progress && !some_progress && (_endp.isInputShutdown()||_endp.isOutputShutdown())) + _endp.close(); } catch (HttpException e) { @@ -123,13 +127,12 @@ public class AsyncHttpConnection extends HttpConnection { setCurrentConnection(null); _parser.returnBuffers(); + _generator.returnBuffers(); - // Are we write blocked - if (_generator.isCommitted() && !_generator.isComplete() && _endp.isOpen()) - ((AsyncEndPoint)_endp).scheduleWrite(); - else - _generator.returnBuffers(); - + // Check if we are write blocked + if (_generator.isCommitted() && !_generator.isComplete() && _endp.isOpen() && !_endp.isOutputShutdown()) + ((AsyncEndPoint)_endp).scheduleWrite(); // TODO. This should not be required + if (!some_progress) { _total_no_progress++; @@ -137,11 +140,6 @@ public class AsyncHttpConnection extends HttpConnection if (NO_PROGRESS_INFO>0 && _total_no_progress%NO_PROGRESS_INFO==0 && (NO_PROGRESS_CLOSE<=0 || _total_no_progress< NO_PROGRESS_CLOSE)) { LOG.info("EndPoint making no progress: "+_total_no_progress+" "+_endp); - - LOG.setDebugEnabled(true); - Log.getLogger("org.eclipse.jetty.io.nio").getLogger("ssl").setDebugEnabled(true); - Log.getLogger(ChannelEndPoint.class).setDebugEnabled(true); - } if (NO_PROGRESS_CLOSE>0 && _total_no_progress>NO_PROGRESS_CLOSE) @@ -154,7 +152,6 @@ public class AsyncHttpConnection extends HttpConnection } } } - LOG.debug("unhandle {}",this); } return connection; } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java index 26d2fb6071b..3f1d327d75b 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java @@ -453,29 +453,29 @@ public abstract class HttpConnection extends AbstractConnection catch (EofException e) { LOG.debug(e); - _request.setHandled(true); error=true; + _request.setHandled(true); } catch (RuntimeIOException e) { LOG.debug(e); - _request.setHandled(true); error=true; + _request.setHandled(true); } catch (HttpException e) { LOG.debug(e); + error=true; _request.setHandled(true); _response.sendError(e.getStatus(), e.getReason()); - error=true; } catch (Throwable e) { if (e instanceof ThreadDeath) throw (ThreadDeath)e; - error=true; LOG.warn(String.valueOf(_uri),e); + error=true; _request.setHandled(true); _generator.sendError(info==null?400:500, null, null, true); } @@ -509,7 +509,12 @@ public abstract class HttpConnection extends AbstractConnection if(_endp.isOpen()) { if (error) + { _endp.shutdownOutput(); + _generator.setPersistent(false); + if (!_generator.isComplete()) + _response.complete(); + } else { if (!_response.isCommitted() && !_request.isHandled()) diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java index 4a001c9e658..be80f7a9e48 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java @@ -37,8 +37,11 @@ import javax.servlet.http.HttpServletResponse; import junit.framework.Assert; +import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.util.IO; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.StdErrLog; import org.junit.Test; /** @@ -108,7 +111,6 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture @Test public void testRequest1() throws Exception { - System.err.println("testRequest1"); configureServer(new HelloWorldHandler()); Socket client=newSocket(HOST,_connector.getLocalPort()); @@ -134,7 +136,6 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture @Test public void testFragmentedChunk() throws Exception { - System.err.println("testFragmentedChunk"); configureServer(new EchoHandler()); Socket client=newSocket(HOST,_connector.getLocalPort()); @@ -168,7 +169,6 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture @Test public void testRequest1Fragments() throws Exception, InterruptedException { - System.err.println("testRequest1Fragments"); configureServer(new HelloWorldHandler()); Socket client=newSocket(HOST,_connector.getLocalPort()); @@ -202,7 +202,6 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture @Test public void testRequest2() throws Exception { - System.err.println("testRequest2"); configureServer(new EchoHandler()); byte[] bytes=REQUEST2.getBytes(); @@ -232,7 +231,6 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture @Test public void testRequest2Fragments() throws Exception { - System.err.println("testRequest2Fragments"); configureServer(new EchoHandler()); byte[] bytes=REQUEST2.getBytes(); @@ -277,7 +275,6 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture @Test public void testRequest2Iterate() throws Exception { - System.err.println("testRequest2Iterate"); configureServer(new EchoHandler()); byte[] bytes=REQUEST2.getBytes(); @@ -317,7 +314,6 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture @Test public void testRequest2KnownBad() throws Exception { - System.err.println("testRequest2KnownBad"); configureServer(new EchoHandler()); byte[] bytes=REQUEST2.getBytes(); @@ -356,7 +352,6 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture @Test public void testFlush() throws Exception { - System.err.println("testFlush"); configureServer(new DataHandler()); String[] encoding = {"NONE","UTF-8","ISO-8859-1","ISO-8859-2"}; @@ -393,7 +388,6 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture @Test public void testBlockingWhileReadingRequestContent() throws Exception { - System.err.println("testBlockingWhileReadingRequestContent"); configureServer(new DataHandler()); long start=System.currentTimeMillis(); @@ -452,7 +446,6 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture @Test public void testBlockingWhileWritingResponseContent() throws Exception { - System.err.println("testBlockingWhileWritingResponseContent"); configureServer(new DataHandler()); long start=System.currentTimeMillis(); @@ -498,7 +491,6 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture @Test public void testBigBlocks() throws Exception { - System.err.println("testBigBlocks"); configureServer(new BigBlockHandler()); Socket client=newSocket(HOST,_connector.getLocalPort()); @@ -632,7 +624,6 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture @Test public void testPipeline() throws Exception { - System.err.println("testPipeline"); configureServer(new HelloWorldHandler()); //for (int pipeline=1;pipeline<32;pipeline++) @@ -689,7 +680,6 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture @Test public void testRecycledWriters() throws Exception { - System.err.println("testRecycledWriters"); configureServer(new EchoHandler()); Socket client=newSocket(HOST,_connector.getLocalPort()); @@ -778,7 +768,6 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture @Test public void testHead() throws Exception { - System.err.println("testHead"); configureServer(new EchoHandler(false)); Socket client=newSocket(HOST,_connector.getLocalPort()); @@ -831,7 +820,6 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture @Test public void testRecycledReaders() throws Exception { - System.err.println("testRecycledReaders"); configureServer(new EchoHandler()); Socket client=newSocket(HOST,_connector.getLocalPort()); @@ -891,7 +879,6 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture @Test public void testBlockedClient() throws Exception { - System.err.println("testBlockedClient"); configureServer(new HelloWorldHandler()); Socket client=newSocket(HOST,_connector.getLocalPort()); @@ -933,12 +920,13 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture @Test public void testCommittedError() throws Exception { - System.err.println("testCommittedError"); - configureServer(new CommittedErrorHandler()); + CommittedErrorHandler handler =new CommittedErrorHandler(); + configureServer(handler); Socket client=newSocket(HOST,_connector.getLocalPort()); try { + ((StdErrLog)Log.getLogger(HttpConnection.class)).setHideStacks(true); OutputStream os=client.getOutputStream(); InputStream is=client.getInputStream(); @@ -946,37 +934,45 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture os.write(( "GET / HTTP/1.1\r\n"+ "Host: "+HOST+":"+_connector.getLocalPort()+"\r\n" + - "Connection: close\r\n"+ "\r\n" ).getBytes()); os.flush(); client.setSoTimeout(2000); String in = IO.toString(is); - System.err.println("in="+in); - - Thread.sleep(2000); + assertEquals(-1,is.read()); // Closed by error! + + assertTrue(in.indexOf("HTTP/1.1 200 OK")>=0); + assertTrue(in.indexOf("Transfer-Encoding: chunked")>0); + assertTrue(in.indexOf("Now is the time for all good men to come to the aid of the party")>0); + assertTrue(in.indexOf("\r\n0\r\n")==-1); // chunking is interrupted by error close + + assertTrue(!handler._endp.isBlocking() || handler._endp.isOutputShutdown()); // oshut + client.close(); + Thread.sleep(100); + assertTrue(!handler._endp.isOpen()); } finally { - System.err.println("closing"); - client.close(); - Thread.sleep(2000); + ((StdErrLog)Log.getLogger(HttpConnection.class)).setHideStacks(false); - System.err.println("FINALLY"); - Thread.sleep(2000); + if (!client.isClosed()) + client.close(); } } protected static class CommittedErrorHandler extends AbstractHandler { + public EndPoint _endp; + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { + _endp=baseRequest.getConnection().getEndPoint(); response.setHeader("test","value"); response.setStatus(200); response.setContentType("text/plain"); - response.getWriter().println("Now is the time for all good ment to come to the aid of the party"); + response.getWriter().println("Now is the time for all good men to come to the aid of the party"); response.getWriter().flush(); response.flushBuffer(); diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/SelectChannelServerTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/SelectChannelServerTest.java index ba0569f231b..d32593a83e2 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/SelectChannelServerTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/SelectChannelServerTest.java @@ -25,10 +25,12 @@ public class SelectChannelServerTest extends HttpServerTestBase { startServer(new SelectChannelConnector()); } - + @Override - public void testBigBlocks() throws Exception + public void testCommittedError() throws Exception { - super.testBigBlocks(); + super.testCommittedError(); } + + }