diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelState.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelState.java index d323049e9910..e96b2e97987c 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelState.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelState.java @@ -155,6 +155,7 @@ public enum Action private boolean _asyncWritePossible; private long _timeoutMs = DEFAULT_TIMEOUT; private AsyncContextEvent _event; + private Thread _onTimeoutThread; protected HttpChannelState(HttpChannel channel) { @@ -582,7 +583,10 @@ public void dispatch(ServletContext context, String path) switch (_requestState) { case ASYNC: + break; case EXPIRING: + if (Thread.currentThread() != _onTimeoutThread) + throw new IllegalStateException(this.getStatusStringLocked()); break; default: throw new IllegalStateException(this.getStatusStringLocked()); @@ -646,36 +650,47 @@ protected void onTimeout() throw new IllegalStateException(toStringLocked()); event = _event; listeners = _asyncListeners; + _onTimeoutThread = Thread.currentThread(); } - if (listeners != null) + try { - Runnable task = new Runnable() + if (listeners != null) { - @Override - public void run() + Runnable task = new Runnable() { - for (AsyncListener listener : listeners) + @Override + public void run() { - try - { - listener.onTimeout(event); - } - catch (Throwable x) + for (AsyncListener listener : listeners) { - LOG.warn("{} while invoking onTimeout listener {}", x, listener, x); + try + { + listener.onTimeout(event); + } + catch (Throwable x) + { + LOG.warn("{} while invoking onTimeout listener {}", x, listener, x); + } } } - } - @Override - public String toString() - { - return "onTimeout"; - } - }; + @Override + public String toString() + { + return "onTimeout"; + } + }; - runInContext(event, task); + runInContext(event, task); + } + } + finally + { + synchronized (this) + { + _onTimeoutThread = null; + } } } @@ -692,6 +707,11 @@ public void complete() switch (_requestState) { case EXPIRING: + if (Thread.currentThread() != _onTimeoutThread) + throw new IllegalStateException(this.getStatusStringLocked()); + _requestState = _sendError ? RequestState.BLOCKING : RequestState.COMPLETE; + break; + case ASYNC: _requestState = _sendError ? RequestState.BLOCKING : RequestState.COMPLETE; break;