This is an automated email from the ASF dual-hosted git repository.
markt pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/main by this push:
new 7d50e72fa0 Handle NPE observed in unit tests and reported on users
list.
7d50e72fa0 is described below
commit 7d50e72fa00ad6eeab6e64ec9d34b7cc606e5a96
Author: Mark Thomas <[email protected]>
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 9dd3f11197..c093f7d26a 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();
@@ -121,8 +119,7 @@ public class CoyoteOutputStream extends ServletOutputStream
{
try {
ob.write(from);
} catch (IOException ioe) {
- ob.setErrorException(ioe);
- throw ioe;
+ handleIOException(ioe);
}
if (nonBlocking) {
checkRegisterForWrite();
@@ -139,8 +136,7 @@ public class CoyoteOutputStream extends ServletOutputStream
{
try {
ob.flush();
} catch (IOException ioe) {
- ob.setErrorException(ioe);
- throw ioe;
+ handleIOException(ioe);
}
if (nonBlocking) {
checkRegisterForWrite();
@@ -179,8 +175,7 @@ public class CoyoteOutputStream extends ServletOutputStream
{
try {
ob.close();
} catch (IOException ioe) {
- ob.setErrorException(ioe);
- throw ioe;
+ handleIOException(ioe);
}
}
@@ -197,5 +192,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 4f4149c099..e57e9ccc1d 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -199,6 +199,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: [email protected]
For additional commands, e-mail: [email protected]