https://bz.apache.org/bugzilla/show_bug.cgi?id=68037

Mark Thomas <ma...@apache.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
         Resolution|---                         |WONTFIX

--- Comment #7 from Mark Thomas <ma...@apache.org> ---
There is a fundamental difference between synchronous and asynchronous for IO
error handling.

In synchronous servlets, processing is always on a container thread. When an
IOException occurs during the service method (including when thrown by
container code), the container expects to catch it and handle it outside of the
service() method. This offers an opportunity for an application to catch the
IOException inside the service() method and effectively hide it from the
container. This is what happens in this test case - hence the client sees the
408 status code.

In asynchronous servlets, processing may not be on a container thread.
Therefore if an IOException is thrown by the container it has to note this
because it will not have an opportunity to catch and handle the exception later
if on a non-container thread and the container is required to call onError().
Because the container tracks the IOException as soon as it is thrown, it is not
possible for the application to hide the exception from the container. This
means the standard handling for IOException is applied which includes disabling
all further IO on the grounds there is no point in further IO after an
IOException. Hence the client never sees the 408 status code.

The application does have a narrow gap in onError() where you can achieve a
similar result to the synchronous case. Something along the lines of:

public void onError(Throwable t) {
    if (t instanceof SocketTimeoutException) {
        try {
            resp.setStatus(408);
            resp.flushBuffer();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    req.getAsyncContext().complete();
}

The reason you need to use setStatus() is that sendError() also disables
further output (it works in the synchronous case because the container
re-enables output in the error handling but that step is skipped for
asynchronous because the container knows there has been an IOException).

It is a bit of a hack, but then so is catching and swallowing IOException in
service().

I did spend some time seeing looking at the asynchronous error handling but
couldn't see an approach I liked more than the current code.

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to