I've created a class that implements ReadListener and WriteListener, called
EchoListener. It's supposed to echo input to the output stream using the
non-blocking IO api. Most of the time it works, but in one case I'm seeing
requests hang.
I've debugged this a bit and here's what seems to be triggering the request to
hang.
1.) A request comes in.
2.) My servlet handles it and set's up the read / write listeners.
3.) The write listener's onWritePossible method is called.
4.) onWritePossible starts to echo data, reading while it can and writing that
data. In the case that hangs, all of the data is echoed by the call to
onWritePossible.
5.) The request has no more data to read, so the async context should be
completed. In my code, this is triggered by the call to "onAllDataRead()", but
in this case "onAllDataRead()" is never called.
Debugging this further and looking into the code for CoyoteAdapter, it appears
that "onAllDataRead()" is not called if the request is finished during the call
to "onWritePossible".
if (res.getWriteListener() != null &&
status == SocketStatus.OPEN_WRITE) {
...
try {
Thread.currentThread().setContextClassLoader(newCL);
res.onWritePossible();
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
res.getWriteListener().onError(t);
throw t;
} finally {
Thread.currentThread().setContextClassLoader(oldCL);
}
success = true;
}
This is in contrast to a call to "onDataAvailable", which triggers a check and
possibly a call to "onAllDataRead()".
else if (req.getReadListener() != null &&
status == SocketStatus.OPEN_READ) {
...
try {
Thread.currentThread().setContextClassLoader(newCL);
req.getReadListener().onDataAvailable();
if (request.isFinished()) {
req.getReadListener().onAllDataRead();
}
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
req.getReadListener().onError(t);
throw t;
} finally {
Thread.currentThread().setContextClassLoader(oldCL);
}
success = true;
}
My question, should the "onAllDataRead()" method be called in this situation?
The spec says "onAllDataRead method is invoked when you have finished reading
all the data for the ServletRequest for which the listener was registered.",
however it's referring to the ReadListener and in this case "onWritePossible"
(i.e. my WriteListener) is reading the data.
Thanks
Dan
PS. I have a test case which I can include to replicate the behavior if needed.
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]