430273 Cancel async timeout breaks volatile link to avoid race with slow expire

This commit is contained in:
Greg Wilkins 2014-03-14 10:27:32 +11:00
parent 2b59cd305d
commit d76c786803
6 changed files with 30 additions and 22 deletions

View File

@ -29,14 +29,14 @@ import javax.servlet.ServletResponse;
import org.eclipse.jetty.server.handler.ContextHandler.Context; import org.eclipse.jetty.server.handler.ContextHandler.Context;
import org.eclipse.jetty.util.thread.Scheduler; import org.eclipse.jetty.util.thread.Scheduler;
public class AsyncContextEvent extends AsyncEvent public class AsyncContextEvent extends AsyncEvent implements Runnable
{ {
final private Context _context; final private Context _context;
final private AsyncContextState _asyncContext; final private AsyncContextState _asyncContext;
volatile HttpChannelState _state; private volatile HttpChannelState _state;
private ServletContext _dispatchContext; private ServletContext _dispatchContext;
private String _dispatchPath; private String _dispatchPath;
private Scheduler.Task _timeoutTask; private volatile Scheduler.Task _timeoutTask;
private Throwable _throwable; private Throwable _throwable;
public AsyncContextEvent(Context context,AsyncContextState asyncContext, HttpChannelState state, Request baseRequest, ServletRequest request, ServletResponse response) public AsyncContextEvent(Context context,AsyncContextState asyncContext, HttpChannelState state, Request baseRequest, ServletRequest request, ServletResponse response)
@ -143,6 +143,7 @@ public class AsyncContextEvent extends AsyncEvent
public void completed() public void completed()
{ {
_timeoutTask=null;
_asyncContext.reset(); _asyncContext.reset();
} }
@ -151,4 +152,13 @@ public class AsyncContextEvent extends AsyncEvent
return _state; return _state;
} }
@Override
public void run()
{
Scheduler.Task task=_timeoutTask;
_timeoutTask=null;
if (task!=null)
_state.expired();
}
} }

View File

@ -307,7 +307,8 @@ public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable
_response.setStatusWithReason(500,reason); _response.setStatusWithReason(500,reason);
ErrorHandler eh = _state.getContextHandler().getErrorHandler();
ErrorHandler eh = ErrorHandler.getErrorHandler(getServer(),_state.getContextHandler());
if (eh instanceof ErrorHandler.ErrorPageMapper) if (eh instanceof ErrorHandler.ErrorPageMapper)
{ {
String error_page=((ErrorHandler.ErrorPageMapper)eh).getErrorPage((HttpServletRequest)_state.getAsyncContextEvent().getSuppliedRequest()); String error_page=((ErrorHandler.ErrorPageMapper)eh).getErrorPage((HttpServletRequest)_state.getAsyncContextEvent().getSuppliedRequest());

View File

@ -537,7 +537,7 @@ public class HttpChannelState
{ {
Scheduler scheduler = _channel.getScheduler(); Scheduler scheduler = _channel.getScheduler();
if (scheduler!=null && _timeoutMs>0) if (scheduler!=null && _timeoutMs>0)
_event.setTimeoutTask(scheduler.schedule(new AsyncTimeout(),_timeoutMs,TimeUnit.MILLISECONDS)); _event.setTimeoutTask(scheduler.schedule(_event,_timeoutMs,TimeUnit.MILLISECONDS));
} }
protected void cancelTimeout() protected void cancelTimeout()
@ -691,13 +691,4 @@ public class HttpChannelState
_channel.execute(_channel); _channel.execute(_channel);
} }
public class AsyncTimeout implements Runnable
{
@Override
public void run()
{
HttpChannelState.this.expired();
}
}
} }

View File

@ -581,13 +581,7 @@ public class Response implements HttpServletResponse
code!=SC_PARTIAL_CONTENT && code!=SC_PARTIAL_CONTENT &&
code>=SC_OK) code>=SC_OK)
{ {
ErrorHandler error_handler = ErrorHandler.getErrorHandler(_channel.getServer(),request.getContext()==null?null:request.getContext().getContextHandler());
ErrorHandler error_handler = null;
ContextHandler.Context context = request.getContext();
if (context!=null)
error_handler=context.getContextHandler().getErrorHandler();
if (error_handler==null)
error_handler = _channel.getServer().getBean(ErrorHandler.class);
if (error_handler!=null) if (error_handler!=null)
{ {
request.setAttribute(RequestDispatcher.ERROR_STATUS_CODE,new Integer(code)); request.setAttribute(RequestDispatcher.ERROR_STATUS_CODE,new Integer(code));

View File

@ -36,6 +36,7 @@ import org.eclipse.jetty.http.MimeTypes;
import org.eclipse.jetty.server.Dispatcher; import org.eclipse.jetty.server.Dispatcher;
import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Response; import org.eclipse.jetty.server.Response;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.ByteArrayISO8859Writer; import org.eclipse.jetty.util.ByteArrayISO8859Writer;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
@ -304,4 +305,15 @@ public class ErrorHandler extends AbstractHandler
{ {
String getErrorPage(HttpServletRequest request); String getErrorPage(HttpServletRequest request);
} }
/* ------------------------------------------------------------ */
public static ErrorHandler getErrorHandler(Server server, ContextHandler context)
{
ErrorHandler error_handler=null;
if (context!=null)
error_handler=context.getErrorHandler();
if (error_handler==null && server!=null)
error_handler = server.getBean(ErrorHandler.class);
return error_handler;
}
} }

View File

@ -414,7 +414,7 @@
<module>jetty-servlet</module> <module>jetty-servlet</module>
<module>jetty-webapp</module> <module>jetty-webapp</module>
<module>jetty-spdy</module> <module>jetty-spdy</module>
<module>jetty-fcgi</module> <!--module>jetty-fcgi</module-->
<module>jetty-websocket</module> <module>jetty-websocket</module>
<module>jetty-servlets</module> <module>jetty-servlets</module>
<module>jetty-util-ajax</module> <module>jetty-util-ajax</module>