This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 10.1.x in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/10.1.x by this push: new 657e547943 Handle NPE observed in unit tests and reported on users list. 657e547943 is described below commit 657e547943ec164a27718249b0a0d8a1c27aae98 Author: Mark Thomas <ma...@apache.org> AuthorDate: Thu Jan 23 16:28:20 2025 +0000 Handle NPE observed in unit tests and reported on users list. NPE occurs after an IOException on a non-container thread during asynchronous processing. --- .../catalina/connector/CoyoteOutputStream.java | 39 ++++++++++++++++------ webapps/docs/changelog.xml | 5 +++ 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/java/org/apache/catalina/connector/CoyoteOutputStream.java b/java/org/apache/catalina/connector/CoyoteOutputStream.java index 139b1e6eb5..7ad7dc4102 100644 --- a/java/org/apache/catalina/connector/CoyoteOutputStream.java +++ b/java/org/apache/catalina/connector/CoyoteOutputStream.java @@ -81,8 +81,7 @@ public class CoyoteOutputStream extends ServletOutputStream { try { ob.writeByte(i); } catch (IOException ioe) { - ob.setErrorException(ioe); - throw ioe; + handleIOException(ioe); } if (nonBlocking) { checkRegisterForWrite(); @@ -102,8 +101,7 @@ public class CoyoteOutputStream extends ServletOutputStream { try { ob.write(b, off, len); } catch (IOException ioe) { - ob.setErrorException(ioe); - throw ioe; + handleIOException(ioe); } if (nonBlocking) { checkRegisterForWrite(); @@ -117,8 +115,7 @@ public class CoyoteOutputStream extends ServletOutputStream { try { ob.write(from); } catch (IOException ioe) { - ob.setErrorException(ioe); - throw ioe; + handleIOException(ioe); } if (nonBlocking) { checkRegisterForWrite(); @@ -135,8 +132,7 @@ public class CoyoteOutputStream extends ServletOutputStream { try { ob.flush(); } catch (IOException ioe) { - ob.setErrorException(ioe); - throw ioe; + handleIOException(ioe); } if (nonBlocking) { checkRegisterForWrite(); @@ -175,8 +171,7 @@ public class CoyoteOutputStream extends ServletOutputStream { try { ob.close(); } catch (IOException ioe) { - ob.setErrorException(ioe); - throw ioe; + handleIOException(ioe); } } @@ -193,5 +188,29 @@ public class CoyoteOutputStream extends ServletOutputStream { public void setWriteListener(WriteListener listener) { ob.setWriteListener(listener); } + + + private void handleIOException(IOException ioe) throws IOException { + try { + ob.setErrorException(ioe); + } catch (NullPointerException npe) { + /* + * Ignore. + * + * An IOException on a non-container thread during asynchronous Servlet processing will trigger a dispatch + * to a container thread that will complete the asynchronous processing and recycle the request, response + * and associated objects including the OutputBuffer. Depending on timing it is possible that the + * OutputBuffer will have been cleared by the time the call above is made - resulting in an NPE. + * + * If the OutputBuffer is null then there is no need to call setErrorException(). Catching and ignoring the + * NPE is (for now at least) a simpler solution than adding locking to OutputBuffer to ensure it is non-null + * and remains non-null while setErrorException() is called. + * + * The longer term solution is likely a refactoring and clean-up of error handling for asynchronous requests + * but that is potentially a significant piece of work. + */ + } + throw ioe; + } } diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml index 5ee3a83665..3d66c9a2c2 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -176,6 +176,11 @@ control over the handling of the path used to created a <code>RequestDispatcher</code>. (markt) </add> + <fix> + Handle a potential <code>NullPointerException</code> after an + <code>IOException</code> occurs on a non-container thread during + asynchronous processing. (markt) + </fix> </changelog> </subsection> <subsection name="Coyote"> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org