JETTY-547 delay close after shutdown

git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@1948 7e9141cc-0065-0410-87d8-b60c137991c4
This commit is contained in:
Greg Wilkins 2010-06-09 06:11:12 +00:00
parent 3a1758ce6f
commit 21f0c161d2
12 changed files with 93 additions and 69 deletions

View File

@ -18,6 +18,7 @@ jetty-7.1.4-SNAPSHOT
+ 315925 Improved context xml configuration handling + 315925 Improved context xml configuration handling
+ 315995 Incorrect package name in system classes list + 315995 Incorrect package name in system classes list
+ 316119 Fixed maxIdleTime for SocketEndPoint + 316119 Fixed maxIdleTime for SocketEndPoint
+ JETTY-547 Delay close after shutdown until request read
+ JETTY-1231 Support context request log handler + JETTY-1231 Support context request log handler
jetty-7.1.3.v20100526 jetty-7.1.3.v20100526

View File

@ -434,24 +434,30 @@ public abstract class AbstractGenerator implements Generator
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** /**
* Utility method to send an error response. If the builder is not committed, this call is * Utility method to send an error response. If the builder is not committed, this call is
* equivalent to a setResponse, addcontent and complete call. * equivalent to a setResponse, addContent and complete call.
* *
* @param code * @param code The error code
* @param reason * @param reason The error reason
* @param content * @param content Contents of the error page
* @param close * @param close True if the connection should be closed
* @throws IOException * @throws IOException if there is a problem flushing the response
*/ */
public void sendError(int code, String reason, String content, boolean close) throws IOException public void sendError(int code, String reason, String content, boolean close) throws IOException
{ {
if (close)
_persistent=false;
if (!isCommitted()) if (!isCommitted())
{ {
setResponse(code, reason); setResponse(code, reason);
if (close)
_persistent=false;
completeHeader(null, false);
if (content != null) if (content != null)
{
completeHeader(null, false);
addContent(new View(new ByteArrayBuffer(content)), Generator.LAST); addContent(new View(new ByteArrayBuffer(content)), Generator.LAST);
}
else
{
completeHeader(null, true);
}
complete(); complete();
} }
} }

View File

@ -885,8 +885,8 @@ public class HttpGenerator extends AbstractGenerator
{ {
if (_state == STATE_FLUSHING) if (_state == STATE_FLUSHING)
_state = STATE_END; _state = STATE_END;
if (_state==STATE_END && !_persistent && _status!=100) if (_state==STATE_END && !_persistent && _status!=100 && _method==null)
_endp.close(); _endp.shutdownOutput();
} }
else else
// Try to prepare more to write. // Try to prepare more to write.

View File

@ -151,6 +151,14 @@ public class ByteArrayEndPoint implements ConnectedEndPoint
return true; return true;
} }
/* ------------------------------------------------------------ */
/*
* @see org.eclipse.io.EndPoint#shutdownOutput()
*/
public void shutdownOutput() throws IOException
{
}
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/* /*
* @see org.eclipse.io.EndPoint#close() * @see org.eclipse.io.EndPoint#close()

View File

@ -23,7 +23,12 @@ import java.io.IOException;
public interface EndPoint public interface EndPoint
{ {
/** /**
* Close any backing stream associated with the buffer * Shutdown any backing output stream associated with the endpoint
*/
void shutdownOutput() throws IOException;
/**
* Close any backing stream associated with the endpoint
*/ */
void close() throws IOException; void close() throws IOException;

View File

@ -65,27 +65,25 @@ public class SocketEndPoint extends StreamEndPoint
return super.isOpen() && _socket!=null && !_socket.isClosed() && !_socket.isInputShutdown() && !_socket.isOutputShutdown(); return super.isOpen() && _socket!=null && !_socket.isClosed() && !_socket.isInputShutdown() && !_socket.isOutputShutdown();
} }
/* ------------------------------------------------------------ */
/*
* @see org.eclipse.jetty.io.bio.StreamEndPoint#shutdownOutput()
*/
@Override
public void shutdownOutput() throws IOException
{
if (!_socket.isClosed() && !_socket.isOutputShutdown())
_socket.shutdownOutput();
}
/* (non-Javadoc) /* (non-Javadoc)
* @see org.eclipse.io.BufferIO#close() * @see org.eclipse.io.BufferIO#close()
*/ */
@Override @Override
public void close() throws IOException public void close() throws IOException
{ {
if (!_socket.isClosed() && !_socket.isOutputShutdown())
{
try
{
_socket.shutdownOutput();
}
catch(IOException e)
{
Log.ignore(e);
}
catch(UnsupportedOperationException e)
{
Log.ignore(e);
}
}
_socket.close(); _socket.close();
_in=null; _in=null;
_out=null; _out=null;

View File

@ -73,6 +73,10 @@ public class StreamEndPoint implements EndPoint
return !isOpen(); return !isOpen();
} }
public void shutdownOutput() throws IOException
{
}
/* /*
* @see org.eclipse.io.BufferIO#close() * @see org.eclipse.io.BufferIO#close()
*/ */

View File

@ -90,36 +90,25 @@ public class ChannelEndPoint implements EndPoint
return _channel.isOpen(); return _channel.isOpen();
} }
/* (non-Javadoc)
* @see org.eclipse.io.EndPoint#close()
*/
public void shutdownOutput() throws IOException
{
if (_channel.isOpen() && _channel instanceof SocketChannel)
{
Socket socket= ((SocketChannel)_channel).socket();
if (!socket.isClosed()&&!socket.isOutputShutdown())
socket.shutdownOutput();
}
}
/* (non-Javadoc) /* (non-Javadoc)
* @see org.eclipse.io.EndPoint#close() * @see org.eclipse.io.EndPoint#close()
*/ */
public void close() throws IOException public void close() throws IOException
{ {
if (_channel.isOpen()) _channel.close();
{
try
{
if (_channel instanceof SocketChannel)
{
// TODO - is this really required?
Socket socket= ((SocketChannel)_channel).socket();
if (!socket.isClosed()&&!socket.isOutputShutdown())
socket.shutdownOutput();
}
}
catch(IOException e)
{
Log.ignore(e);
}
catch(UnsupportedOperationException e)
{
Log.ignore(e);
}
finally
{
_channel.close();
}
}
} }
/* (non-Javadoc) /* (non-Javadoc)

View File

@ -143,14 +143,11 @@ public class SslSelectChannelEndPoint extends SelectChannelEndPoint
{ {
Log.info(""+_result); Log.info(""+_result);
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@Override @Override
public void close() throws IOException public void shutdownOutput() throws IOException
{ {
// TODO - this really should not be done in a loop here - but with async callbacks. // TODO - this really should not be done in a loop here - but with async callbacks.
_closing=true;
long end=System.currentTimeMillis()+((SocketChannel)_channel).socket().getSoTimeout(); long end=System.currentTimeMillis()+((SocketChannel)_channel).socket().getSoTimeout();
try try
{ {
@ -241,11 +238,23 @@ public class SslSelectChannelEndPoint extends SelectChannelEndPoint
} }
} }
} }
catch(IOException e) catch (InterruptedException e)
{ {
Log.ignore(e); Log.ignore(e);
} }
catch (InterruptedException e) }
/* ------------------------------------------------------------ */
@Override
public void close() throws IOException
{
try
{
_closing=true;
shutdownOutput();
}
catch(IOException e)
{ {
Log.ignore(e); Log.ignore(e);
} }

View File

@ -489,6 +489,7 @@ public class HttpConnection implements Connection
{ {
_parser.reset(true); _parser.reset(true);
more_in_buffer=false; more_in_buffer=false;
_endp.close();
} }
if (more_in_buffer) if (more_in_buffer)
@ -632,7 +633,6 @@ public class HttpConnection implements Connection
Log.debug(e); Log.debug(e);
_request.setHandled(true); _request.setHandled(true);
_generator.sendError(info==null?400:500, null, null, true); _generator.sendError(info==null?400:500, null, null, true);
} }
finally finally
{ {
@ -1019,7 +1019,10 @@ public class HttpConnection implements Connection
if (_expect) if (_expect)
{ {
_generator.sendError(HttpStatus.EXPECTATION_FAILED_417, null, null, true); _generator.setResponse(HttpStatus.EXPECTATION_FAILED_417, null);
_responseFields.put(HttpHeaders.CONNECTION_BUFFER, HttpHeaderValues.CLOSE_BUFFER);
_generator.completeHeader(_responseFields, true);
_generator.complete();
return; return;
} }

View File

@ -137,7 +137,7 @@ public class SslSocketConnector extends SocketConnector implements SslConnector
Socket socket = _serverSocket.accept(); Socket socket = _serverSocket.accept();
configure(socket); configure(socket);
ConnectorEndPoint connection=new SslConnection(socket); ConnectorEndPoint connection=new SslConnectorEndPoint(socket);
connection.dispatch(); connection.dispatch();
} }
@ -606,13 +606,18 @@ public class SslSocketConnector extends SocketConnector implements SslConnector
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
public class SslConnection extends ConnectorEndPoint public class SslConnectorEndPoint extends ConnectorEndPoint
{ {
public SslConnection(Socket socket) throws IOException public SslConnectorEndPoint(Socket socket) throws IOException
{ {
super(socket); super(socket);
} }
@Override
public void shutdownOutput() throws IOException
{
}
@Override @Override
public void run() public void run()
{ {

View File

@ -661,7 +661,8 @@ public abstract class RFC2616BaseTest
req2.append("Expect: unknown\n"); // Invalid Expect header. req2.append("Expect: unknown\n"); // Invalid Expect header.
req2.append("Content-Type: text/plain\n"); req2.append("Content-Type: text/plain\n");
req2.append("Content-Length: 8\n"); req2.append("Content-Length: 8\n");
req2.append("\n"); // No body req2.append("\n");
req2.append("12345678\n");
response = http.request(req2); response = http.request(req2);
@ -976,7 +977,6 @@ public abstract class RFC2616BaseTest
req2.append("Range: bytes=1-3\n"); // request first 3 bytes req2.append("Range: bytes=1-3\n"); // request first 3 bytes
req2.append("\n"); req2.append("\n");
http.enableDebug();
response = http.request(req2); response = http.request(req2);
response.assertStatus("10.2.7 Partial Content",HttpStatus.PARTIAL_CONTENT_206); response.assertStatus("10.2.7 Partial Content",HttpStatus.PARTIAL_CONTENT_206);
@ -1260,7 +1260,6 @@ public abstract class RFC2616BaseTest
req1.append("\n"); req1.append("\n");
http.setTimeoutMillis(60000); http.setTimeoutMillis(60000);
http.enableDebug();
response = http.request(req1); response = http.request(req1);
String msg = "Partial Range (Mixed): 'bytes=a-b,5-8'"; String msg = "Partial Range (Mixed): 'bytes=a-b,5-8'";
@ -1449,7 +1448,6 @@ public abstract class RFC2616BaseTest
req1.append("Connection: close\n"); req1.append("Connection: close\n");
req1.append("\n"); req1.append("\n");
http.enableDebug();
response = http.request(req1); response = http.request(req1);
String msg = "Partial (Byte) Range: '" + rangedef + "'"; String msg = "Partial (Byte) Range: '" + rangedef + "'";
@ -1567,7 +1565,6 @@ public abstract class RFC2616BaseTest
req1.append("Connection: close\n"); req1.append("Connection: close\n");
req1.append("\n"); req1.append("\n");
http.enableDebug();
response = http.request(req1); response = http.request(req1);
String msg = "Partial (Byte) Range: '" + rangedef + "'"; String msg = "Partial (Byte) Range: '" + rangedef + "'";
@ -1689,7 +1686,6 @@ public abstract class RFC2616BaseTest
req1.append("Connection: close\n"); req1.append("Connection: close\n");
req1.append("\n"); req1.append("\n");
http.enableDebug();
response = http.request(req1); response = http.request(req1);
specId = "14.39 TE Header"; specId = "14.39 TE Header";
response.assertStatusOK(specId); response.assertStatusOK(specId);