362854 - Continuation implementations may deadlock.
HttpChannelState was already notifying listeners from outside synchronized blocks, apart one case, in expired(). Also taken the chance to cleanup the class from warnings.
This commit is contained in:
parent
ef81982579
commit
6d0f233c80
|
@ -21,7 +21,6 @@ package org.eclipse.jetty.server;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.servlet.AsyncContext;
|
||||
import javax.servlet.AsyncEvent;
|
||||
import javax.servlet.AsyncListener;
|
||||
|
@ -39,8 +38,8 @@ import org.eclipse.jetty.util.log.Log;
|
|||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.util.thread.Scheduler;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Implementation of AsyncContext interface that holds the state of request-response cycle.
|
||||
/**
|
||||
* Implementation of AsyncContext interface that holds the state of request-response cycle.
|
||||
*
|
||||
* <table>
|
||||
* <tr><th>STATE</th><th colspan=6>ACTION</th></tr>
|
||||
|
@ -56,7 +55,6 @@ import org.eclipse.jetty.util.thread.Scheduler;
|
|||
* <tr><th align=right>COMPLETING:</th> <td>COMPLETING</td> <td></td> <td></td> <td></td> <td></td> <td>COMPLETED</td></tr>
|
||||
* <tr><th align=right>COMPLETED:</th> <td></td> <td></td> <td></td> <td></td> <td></td> <td></td></tr>
|
||||
* </table>
|
||||
*
|
||||
*/
|
||||
public class HttpChannelState implements AsyncContext
|
||||
{
|
||||
|
@ -78,12 +76,10 @@ public class HttpChannelState implements AsyncContext
|
|||
COMPLETED // Request is complete
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
private final HttpChannel<?> _channel;
|
||||
private List<AsyncListener> _lastAsyncListeners;
|
||||
private List<AsyncListener> _asyncListeners;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
private State _state;
|
||||
private boolean _initial;
|
||||
private boolean _dispatched;
|
||||
|
@ -92,7 +88,6 @@ public class HttpChannelState implements AsyncContext
|
|||
private long _timeoutMs=DEFAULT_TIMEOUT;
|
||||
private AsyncEventState _event;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected HttpChannelState(HttpChannel<?> channel)
|
||||
{
|
||||
_channel=channel;
|
||||
|
@ -100,7 +95,6 @@ public class HttpChannelState implements AsyncContext
|
|||
_initial=true;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public State getState()
|
||||
{
|
||||
synchronized(this)
|
||||
|
@ -109,7 +103,6 @@ public class HttpChannelState implements AsyncContext
|
|||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public void addListener(AsyncListener listener)
|
||||
{
|
||||
|
@ -121,7 +114,6 @@ public class HttpChannelState implements AsyncContext
|
|||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public void addListener(AsyncListener listener,ServletRequest request, ServletResponse response)
|
||||
{
|
||||
|
@ -134,7 +126,6 @@ public class HttpChannelState implements AsyncContext
|
|||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public void setTimeout(long ms)
|
||||
{
|
||||
|
@ -144,7 +135,6 @@ public class HttpChannelState implements AsyncContext
|
|||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public long getTimeout()
|
||||
{
|
||||
|
@ -154,7 +144,6 @@ public class HttpChannelState implements AsyncContext
|
|||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public AsyncEventState getAsyncEventState()
|
||||
{
|
||||
synchronized(this)
|
||||
|
@ -163,7 +152,6 @@ public class HttpChannelState implements AsyncContext
|
|||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
|
@ -173,7 +161,6 @@ public class HttpChannelState implements AsyncContext
|
|||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public String getStatusString()
|
||||
{
|
||||
synchronized (this)
|
||||
|
@ -185,7 +172,6 @@ public class HttpChannelState implements AsyncContext
|
|||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @return true if the handling of the request should proceed
|
||||
*/
|
||||
|
@ -228,10 +214,10 @@ public class HttpChannelState implements AsyncContext
|
|||
|
||||
_responseWrapped=false;
|
||||
return true;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
public void startAsync()
|
||||
{
|
||||
synchronized (this)
|
||||
|
@ -272,11 +258,7 @@ public class HttpChannelState implements AsyncContext
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* (non-Javadoc)
|
||||
* @see javax.servlet.ServletRequest#suspend(long)
|
||||
*/
|
||||
|
||||
public void startAsync(final ServletContext context,final ServletRequest request,final ServletResponse response)
|
||||
{
|
||||
synchronized (this)
|
||||
|
@ -319,7 +301,6 @@ public class HttpChannelState implements AsyncContext
|
|||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected void error(Throwable th)
|
||||
{
|
||||
synchronized (this)
|
||||
|
@ -329,7 +310,6 @@ public class HttpChannelState implements AsyncContext
|
|||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Signal that the HttpConnection has finished handling the request.
|
||||
* For blocking connectors, this call may block if the request has
|
||||
|
@ -382,11 +362,10 @@ public class HttpChannelState implements AsyncContext
|
|||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public void dispatch()
|
||||
{
|
||||
boolean dispatch=false;
|
||||
boolean dispatch;
|
||||
synchronized (this)
|
||||
{
|
||||
switch(_state)
|
||||
|
@ -417,10 +396,6 @@ public class HttpChannelState implements AsyncContext
|
|||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see Continuation#isDispatched()
|
||||
*/
|
||||
public boolean isDispatched()
|
||||
{
|
||||
synchronized (this)
|
||||
|
@ -428,8 +403,7 @@ public class HttpChannelState implements AsyncContext
|
|||
return _dispatched;
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
protected void expired()
|
||||
{
|
||||
final List<AsyncListener> aListeners;
|
||||
|
@ -442,7 +416,6 @@ public class HttpChannelState implements AsyncContext
|
|||
aListeners=_asyncListeners;
|
||||
break;
|
||||
default:
|
||||
aListeners=null;
|
||||
return;
|
||||
}
|
||||
_expired=true;
|
||||
|
@ -463,29 +436,31 @@ public class HttpChannelState implements AsyncContext
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
boolean complete;
|
||||
synchronized (this)
|
||||
{
|
||||
switch(_state)
|
||||
{
|
||||
case ASYNCSTARTED:
|
||||
case ASYNCWAIT:
|
||||
complete();
|
||||
complete = true;
|
||||
break;
|
||||
default:
|
||||
complete = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (complete)
|
||||
complete();
|
||||
|
||||
scheduleDispatch();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* (non-Javadoc)
|
||||
* @see javax.servlet.ServletRequest#complete()
|
||||
*/
|
||||
@Override
|
||||
public void complete()
|
||||
{
|
||||
// just like resume, except don't set _dispatched=true;
|
||||
boolean dispatch=false;
|
||||
boolean dispatch;
|
||||
synchronized (this)
|
||||
{
|
||||
switch(_state)
|
||||
|
@ -516,13 +491,11 @@ public class HttpChannelState implements AsyncContext
|
|||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public <T extends AsyncListener> T createListener(Class<T> clazz) throws ServletException
|
||||
{
|
||||
try
|
||||
{
|
||||
// TODO inject
|
||||
return clazz.newInstance();
|
||||
}
|
||||
catch(Exception e)
|
||||
|
@ -531,11 +504,6 @@ public class HttpChannelState implements AsyncContext
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* (non-Javadoc)
|
||||
* @see javax.servlet.ServletRequest#complete()
|
||||
*/
|
||||
protected void completed()
|
||||
{
|
||||
final List<AsyncListener> aListeners;
|
||||
|
@ -549,7 +517,6 @@ public class HttpChannelState implements AsyncContext
|
|||
break;
|
||||
|
||||
default:
|
||||
aListeners=null;
|
||||
throw new IllegalStateException(this.getStatusString());
|
||||
}
|
||||
}
|
||||
|
@ -577,7 +544,6 @@ public class HttpChannelState implements AsyncContext
|
|||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected void recycle()
|
||||
{
|
||||
synchronized (this)
|
||||
|
@ -600,7 +566,6 @@ public class HttpChannelState implements AsyncContext
|
|||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void cancel()
|
||||
{
|
||||
synchronized (this)
|
||||
|
@ -609,13 +574,11 @@ public class HttpChannelState implements AsyncContext
|
|||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected void scheduleDispatch()
|
||||
{
|
||||
_channel.execute(_channel);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected void scheduleTimeout()
|
||||
{
|
||||
Scheduler scheduler = _channel.getScheduler();
|
||||
|
@ -623,7 +586,6 @@ public class HttpChannelState implements AsyncContext
|
|||
_event._timeout=scheduler.schedule(new AsyncTimeout(),_timeoutMs,TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected void cancelTimeout()
|
||||
{
|
||||
AsyncEventState event=_event;
|
||||
|
@ -635,10 +597,6 @@ public class HttpChannelState implements AsyncContext
|
|||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* (non-Javadoc)
|
||||
* @see javax.servlet.ServletRequest#isInitial()
|
||||
*/
|
||||
public boolean isInitial()
|
||||
{
|
||||
synchronized(this)
|
||||
|
@ -647,7 +605,6 @@ public class HttpChannelState implements AsyncContext
|
|||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public boolean isSuspended()
|
||||
{
|
||||
synchronized(this)
|
||||
|
@ -666,7 +623,6 @@ public class HttpChannelState implements AsyncContext
|
|||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
boolean isCompleting()
|
||||
{
|
||||
synchronized (this)
|
||||
|
@ -675,13 +631,12 @@ public class HttpChannelState implements AsyncContext
|
|||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public boolean isAsync()
|
||||
{
|
||||
synchronized (this)
|
||||
{
|
||||
switch(_state)
|
||||
{
|
||||
{
|
||||
case ASYNCSTARTED:
|
||||
case REDISPATCHING:
|
||||
case ASYNCWAIT:
|
||||
|
@ -696,7 +651,6 @@ public class HttpChannelState implements AsyncContext
|
|||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public void dispatch(ServletContext context, String path)
|
||||
{
|
||||
|
@ -705,7 +659,6 @@ public class HttpChannelState implements AsyncContext
|
|||
dispatch();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public void dispatch(String path)
|
||||
{
|
||||
|
@ -713,13 +666,11 @@ public class HttpChannelState implements AsyncContext
|
|||
dispatch();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public Request getBaseRequest()
|
||||
{
|
||||
return _channel.getRequest();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public ServletRequest getRequest()
|
||||
{
|
||||
|
@ -728,7 +679,6 @@ public class HttpChannelState implements AsyncContext
|
|||
return _channel.getRequest();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public ServletResponse getResponse()
|
||||
{
|
||||
|
@ -737,7 +687,6 @@ public class HttpChannelState implements AsyncContext
|
|||
return _channel.getResponse();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public void start(final Runnable run)
|
||||
{
|
||||
|
@ -755,7 +704,6 @@ public class HttpChannelState implements AsyncContext
|
|||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public boolean hasOriginalRequestAndResponse()
|
||||
{
|
||||
|
@ -765,7 +713,6 @@ public class HttpChannelState implements AsyncContext
|
|||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public ContextHandler getContextHandler()
|
||||
{
|
||||
final AsyncEventState event=_event;
|
||||
|
@ -774,11 +721,6 @@ public class HttpChannelState implements AsyncContext
|
|||
return null;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.continuation.Continuation#getServletResponse()
|
||||
*/
|
||||
public ServletResponse getServletResponse()
|
||||
{
|
||||
if (_responseWrapped && _event!=null && _event.getSuppliedResponse()!=null)
|
||||
|
@ -786,35 +728,21 @@ public class HttpChannelState implements AsyncContext
|
|||
return _channel.getResponse();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.continuation.Continuation#getAttribute(java.lang.String)
|
||||
*/
|
||||
public Object getAttribute(String name)
|
||||
{
|
||||
return _channel.getRequest().getAttribute(name);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.continuation.Continuation#removeAttribute(java.lang.String)
|
||||
*/
|
||||
public void removeAttribute(String name)
|
||||
{
|
||||
_channel.getRequest().removeAttribute(name);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.continuation.Continuation#setAttribute(java.lang.String, java.lang.Object)
|
||||
*/
|
||||
public void setAttribute(String name, Object attribute)
|
||||
{
|
||||
_channel.getRequest().setAttribute(name,attribute);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------ */
|
||||
public class AsyncTimeout implements Runnable
|
||||
{
|
||||
@Override
|
||||
|
@ -824,8 +752,6 @@ public class HttpChannelState implements AsyncContext
|
|||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------ */
|
||||
public class AsyncEventState extends AsyncEvent
|
||||
{
|
||||
final private ServletContext _suspendedContext;
|
||||
|
@ -838,7 +764,7 @@ public class HttpChannelState implements AsyncContext
|
|||
{
|
||||
super(HttpChannelState.this, request,response);
|
||||
_suspendedContext=context;
|
||||
|
||||
|
||||
// Get the base request So we can remember the initial paths
|
||||
Request r=_channel.getRequest();
|
||||
|
||||
|
@ -884,7 +810,6 @@ public class HttpChannelState implements AsyncContext
|
|||
return _dispatchContext==null?_suspendedContext:_dispatchContext;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @return The path in the context
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue