Issue #10402 - do not recycle ServletChannel if aborted

Signed-off-by: Lachlan Roberts <lachlan@webtide.com>
This commit is contained in:
Lachlan Roberts 2023-08-28 15:46:28 +10:00
parent 5946503ee0
commit 27d0c7a181
4 changed files with 33 additions and 3 deletions

View File

@ -157,6 +157,7 @@ public class ServletChannel
_request = request;
_response = response;
_callback = callback;
_state.open();
if (LOG.isDebugEnabled())
LOG.debug("associate {} -> {},{},{}",
@ -191,6 +192,11 @@ public class ServletChannel
return _httpInput;
}
public boolean isAborted()
{
return _state.isAborted();
}
public boolean isSendError()
{
return _state.isSendError();

View File

@ -113,6 +113,7 @@ public class ServletChannelState
*/
private enum OutputState
{
IDLE,
OPEN,
COMPLETED,
ABORTED,
@ -140,7 +141,7 @@ public class ServletChannelState
private List<AsyncListener> _asyncListeners;
private State _state = State.IDLE;
private RequestState _requestState = RequestState.BLOCKING;
private OutputState _outputState = OutputState.OPEN;
private OutputState _outputState = OutputState.IDLE;
private InputState _inputState = InputState.IDLE;
private boolean _initial = true;
private boolean _sendError;
@ -159,6 +160,24 @@ public class ServletChannelState
return _servletChannel;
}
public boolean isAborted()
{
try (AutoLock ignored = lock())
{
return _outputState == OutputState.ABORTED;
}
}
public void open()
{
try (AutoLock ignored = lock())
{
if (_outputState != OutputState.IDLE)
throw new IllegalStateException(toStringLocked());
_outputState = OutputState.OPEN;
}
}
AutoLock lock()
{
return _lock.lock();
@ -1042,7 +1061,8 @@ public class ServletChannelState
_asyncListeners = null;
_state = State.IDLE;
_requestState = RequestState.BLOCKING;
_outputState = OutputState.OPEN;
if (_outputState != OutputState.ABORTED)
_outputState = OutputState.IDLE;
_initial = true;
_inputState = InputState.IDLE;
_asyncWritePossible = false;

View File

@ -1146,7 +1146,7 @@ public class ServletContextHandler extends ContextHandler
Attributes cache = request.getComponents().getCache();
Object cachedChannel = cache.getAttribute(ServletChannel.class.getName());
ServletChannel servletChannel;
if (cachedChannel instanceof ServletChannel sc && sc.getContext() == getContext())
if (cachedChannel instanceof ServletChannel sc && sc.getContext() == getContext() && !sc.isAborted())
{
servletChannel = sc;
}

View File

@ -714,12 +714,14 @@ public class AsyncServletIOTest
@Override
public void onError(Throwable t)
{
System.err.println("onError");
t.printStackTrace();
}
@Override
public void onDataAvailable() throws IOException
{
System.err.println("onDataAvailable");
onDA.incrementAndGet();
boolean readF = false;
@ -750,6 +752,7 @@ public class AsyncServletIOTest
@Override
public void onWritePossible() throws IOException
{
System.err.println("onWritePossible");
onWP.incrementAndGet();
while (out.isReady())
@ -785,6 +788,7 @@ public class AsyncServletIOTest
@Override
public void onAllDataRead() throws IOException
{
System.err.println("onAllDataRead");
throw new IllegalStateException();
}
});