406390 406617 removed tiny race from handling of suspend and complete
This commit is contained in:
parent
9ad5ab1ed5
commit
7590ad6795
|
@ -43,6 +43,7 @@ import org.eclipse.jetty.io.ByteBufferPool;
|
|||
import org.eclipse.jetty.io.ChannelEndPoint;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.io.EofException;
|
||||
import org.eclipse.jetty.server.HttpChannelState.Next;
|
||||
import org.eclipse.jetty.server.handler.ErrorHandler;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.util.URIUtil;
|
||||
|
@ -216,6 +217,15 @@ public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable
|
|||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
handle();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @return True if the channel is ready to continue handling (ie it is not suspended)
|
||||
*/
|
||||
public boolean handle()
|
||||
{
|
||||
LOG.debug("{} handle enter", this);
|
||||
|
||||
|
@ -228,15 +238,16 @@ public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable
|
|||
Thread.currentThread().setName(threadName + " - " + _uri);
|
||||
}
|
||||
|
||||
|
||||
// Loop here to handle async request redispatches.
|
||||
// The loop is controlled by the call to async.unhandle in the
|
||||
// finally block below. Unhandle will return false only if an async dispatch has
|
||||
// already happened when unhandle is called.
|
||||
HttpChannelState.Next next = _state.handling();
|
||||
try
|
||||
{
|
||||
// Loop here to handle async request redispatches.
|
||||
// The loop is controlled by the call to async.unhandle in the
|
||||
// finally block below. Unhandle will return false only if an async dispatch has
|
||||
// already happened when unhandle is called.
|
||||
boolean handling = _state.handling();
|
||||
|
||||
while (handling && getServer().isRunning())
|
||||
while (next==Next.CONTINUE && getServer().isRunning())
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -286,9 +297,11 @@ public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable
|
|||
}
|
||||
finally
|
||||
{
|
||||
handling = !_state.unhandle();
|
||||
next = _state.unhandle();
|
||||
}
|
||||
}
|
||||
if (next==Next.WAIT)
|
||||
return false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -296,7 +309,7 @@ public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable
|
|||
Thread.currentThread().setName(threadName);
|
||||
setCurrentHttpChannel(null);
|
||||
|
||||
if (_state.isCompleting())
|
||||
if (next==Next.COMPLETE)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -319,13 +332,21 @@ public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable
|
|||
}
|
||||
finally
|
||||
{
|
||||
_request.setHandled(true);
|
||||
_transport.completed();
|
||||
next=Next.RECYCLE;
|
||||
}
|
||||
}
|
||||
|
||||
if (next==Next.RECYCLE)
|
||||
{
|
||||
_request.setHandled(true);
|
||||
_transport.completed();
|
||||
}
|
||||
|
||||
|
||||
LOG.debug("{} handle exit", this);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -570,10 +591,9 @@ public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable
|
|||
|
||||
try
|
||||
{
|
||||
if (_state.handling())
|
||||
if (_state.handling()==Next.CONTINUE)
|
||||
{
|
||||
commitResponse(new ResponseInfo(HttpVersion.HTTP_1_1,new HttpFields(),0,status,reason,false),null,true);
|
||||
_state.unhandle();
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
|
@ -581,8 +601,9 @@ public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable
|
|||
LOG.warn(e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_state.completed();
|
||||
{
|
||||
if (_state.unhandle()==Next.COMPLETE)
|
||||
_state.completed();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -71,6 +71,14 @@ public class HttpChannelState
|
|||
COMPLETING, // Request is completable
|
||||
COMPLETED // Request is complete
|
||||
}
|
||||
|
||||
public enum Next
|
||||
{
|
||||
CONTINUE, // Continue handling the channel
|
||||
WAIT, // Wait for further events
|
||||
COMPLETE, // Complete the channel
|
||||
RECYCLE, // Channel is completed
|
||||
}
|
||||
|
||||
private final HttpChannel<?> _channel;
|
||||
private List<AsyncListener> _lastAsyncListeners;
|
||||
|
@ -154,9 +162,9 @@ public class HttpChannelState
|
|||
}
|
||||
|
||||
/**
|
||||
* @return true if the handling of the request should proceed
|
||||
* @return Next handling of the request should proceed
|
||||
*/
|
||||
protected boolean handling()
|
||||
protected Next handling()
|
||||
{
|
||||
synchronized (this)
|
||||
{
|
||||
|
@ -178,12 +186,16 @@ public class HttpChannelState
|
|||
|
||||
case COMPLETECALLED:
|
||||
_state=State.COMPLETING;
|
||||
return false;
|
||||
return Next.COMPLETE;
|
||||
|
||||
case ASYNCWAIT:
|
||||
case COMPLETING:
|
||||
return Next.COMPLETE;
|
||||
|
||||
case ASYNCWAIT:
|
||||
return Next.WAIT;
|
||||
|
||||
case COMPLETED:
|
||||
return false;
|
||||
return Next.RECYCLE;
|
||||
|
||||
case REDISPATCH:
|
||||
_state=State.REDISPATCHED;
|
||||
|
@ -194,7 +206,7 @@ public class HttpChannelState
|
|||
}
|
||||
|
||||
_responseWrapped=false;
|
||||
return true;
|
||||
return Next.CONTINUE;
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -255,10 +267,10 @@ public class HttpChannelState
|
|||
* Signal that the HttpConnection has finished handling the request.
|
||||
* For blocking connectors, this call may block if the request has
|
||||
* been suspended (startAsync called).
|
||||
* @return true if handling is complete, false if the request should
|
||||
* @return next actions
|
||||
* be handled again (eg because of a resume that happened before unhandle was called)
|
||||
*/
|
||||
protected boolean unhandle()
|
||||
protected Next unhandle()
|
||||
{
|
||||
synchronized (this)
|
||||
{
|
||||
|
@ -267,7 +279,7 @@ public class HttpChannelState
|
|||
case REDISPATCHED:
|
||||
case DISPATCHED:
|
||||
_state=State.COMPLETING;
|
||||
return true;
|
||||
return Next.COMPLETE;
|
||||
|
||||
case IDLE:
|
||||
throw new IllegalStateException(this.getStatusString());
|
||||
|
@ -277,25 +289,25 @@ public class HttpChannelState
|
|||
_state=State.ASYNCWAIT;
|
||||
scheduleTimeout();
|
||||
if (_state==State.ASYNCWAIT)
|
||||
return true;
|
||||
return Next.WAIT;
|
||||
else if (_state==State.COMPLETECALLED)
|
||||
{
|
||||
_state=State.COMPLETING;
|
||||
return true;
|
||||
return Next.COMPLETE;
|
||||
}
|
||||
_initial=false;
|
||||
_state=State.REDISPATCHED;
|
||||
return false;
|
||||
return Next.CONTINUE;
|
||||
|
||||
case REDISPATCHING:
|
||||
_initial=false;
|
||||
_state=State.REDISPATCHED;
|
||||
return false;
|
||||
return Next.CONTINUE;
|
||||
|
||||
case COMPLETECALLED:
|
||||
_initial=false;
|
||||
_state=State.COMPLETING;
|
||||
return true;
|
||||
return Next.COMPLETE;
|
||||
|
||||
default:
|
||||
throw new IllegalStateException(this.getStatusString());
|
||||
|
|
|
@ -222,11 +222,10 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http
|
|||
// The parser returned true, which indicates the channel is ready to handle a request.
|
||||
// Call the channel and this will either handle the request/response to completion OR,
|
||||
// if the request suspends, the request/response will be incomplete so the outer loop will exit.
|
||||
|
||||
_channel.run();
|
||||
boolean handle=_channel.handle();
|
||||
|
||||
// Return if suspended or upgraded
|
||||
if (_channel.getState().isSuspended() || getEndPoint().getConnection()!=this)
|
||||
if (!handle || getEndPoint().getConnection()!=this)
|
||||
return;
|
||||
}
|
||||
else if (BufferUtil.isEmpty(_requestBuffer))
|
||||
|
|
Loading…
Reference in New Issue