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: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org

Reply via email to