Author: markt
Date: Wed Apr 24 11:43:30 2013
New Revision: 1471372

URL: http://svn.apache.org/r1471372
Log:
Protect against AsyncListeners that throw RuntimeExceptions (they should 
normally only throw IOExceptions).
Includes a test case.

Modified:
    tomcat/tc7.0.x/trunk/   (props changed)
    tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/AsyncContextImpl.java
    tomcat/tc7.0.x/trunk/test/org/apache/catalina/core/TestAsyncContextImpl.java
    tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml

Propchange: tomcat/tc7.0.x/trunk/
------------------------------------------------------------------------------
  Merged /tomcat/trunk:r1471371

Modified: 
tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/AsyncContextImpl.java
URL: 
http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/AsyncContextImpl.java?rev=1471372&r1=1471371&r2=1471372&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/AsyncContextImpl.java 
(original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/AsyncContextImpl.java 
Wed Apr 24 11:43:30 2013
@@ -117,9 +117,10 @@ public class AsyncContextImpl implements
             for (AsyncListenerWrapper listener : listenersCopy) {
                 try {
                     listener.fireOnComplete(event);
-                } catch (IOException ioe) {
+                } catch (Throwable t) {
+                    ExceptionUtils.handleThrowable(t);
                     log.warn("onComplete() failed for listener of type [" +
-                            listener.getClass().getName() + "]", ioe);
+                            listener.getClass().getName() + "]", t);
                 }
             }
         } finally {
@@ -148,9 +149,10 @@ public class AsyncContextImpl implements
                 for (AsyncListenerWrapper listener : listenersCopy) {
                     try {
                         listener.fireOnTimeout(event);
-                    } catch (IOException ioe) {
+                    } catch (Throwable t) {
+                        ExceptionUtils.handleThrowable(t);
                         log.warn("onTimeout() failed for listener of type [" +
-                                listener.getClass().getName() + "]", ioe);
+                                listener.getClass().getName() + "]", t);
                     }
                 }
                 request.getCoyoteRequest().action(
@@ -328,9 +330,10 @@ public class AsyncContextImpl implements
         for (AsyncListenerWrapper listener : listenersCopy) {
             try {
                 listener.fireOnStartAsync(event);
-            } catch (IOException ioe) {
+            } catch (Throwable t) {
+                ExceptionUtils.handleThrowable(t);
                 log.warn("onStartAsync() failed for listener of type [" +
-                        listener.getClass().getName() + "]", ioe);
+                        listener.getClass().getName() + "]", t);
             }
         }
         listeners.clear();
@@ -393,9 +396,10 @@ public class AsyncContextImpl implements
             for (AsyncListenerWrapper listener : listenersCopy) {
                 try {
                     listener.fireOnError(errorEvent);
-                } catch (IOException ioe) {
+                } catch (Throwable t2) {
+                    ExceptionUtils.handleThrowable(t);
                     log.warn("onError() failed for listener of type [" +
-                            listener.getClass().getName() + "]", ioe);
+                            listener.getClass().getName() + "]", t2);
                 }
             }
         }

Modified: 
tomcat/tc7.0.x/trunk/test/org/apache/catalina/core/TestAsyncContextImpl.java
URL: 
http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/test/org/apache/catalina/core/TestAsyncContextImpl.java?rev=1471372&r1=1471371&r2=1471372&view=diff
==============================================================================
--- 
tomcat/tc7.0.x/trunk/test/org/apache/catalina/core/TestAsyncContextImpl.java 
(original)
+++ 
tomcat/tc7.0.x/trunk/test/org/apache/catalina/core/TestAsyncContextImpl.java 
Wed Apr 24 11:43:30 2013
@@ -1189,7 +1189,7 @@ public class TestAsyncContextImpl extend
 
         private static final long serialVersionUID = 1L;
 
-        private int status = 200;
+        private int status;
 
         public AsyncStatusServlet(int status) {
             this.status = status;
@@ -1629,4 +1629,108 @@ public class TestAsyncContextImpl extend
             }
         }
     }
+
+    @Test
+    public void testBug54178() throws Exception {
+        // Setup Tomcat instance
+        Tomcat tomcat = getTomcatInstance();
+
+        // Must have a real docBase - just use temp
+        File docBase = new File(System.getProperty("java.io.tmpdir"));
+
+        Context ctx = tomcat.addContext("", docBase.getAbsolutePath());
+
+        Bug54178ServletA bug54178ServletA = new Bug54178ServletA();
+        Wrapper wrapper =
+            Tomcat.addServlet(ctx, "bug54178ServletA", bug54178ServletA);
+        wrapper.setAsyncSupported(true);
+        ctx.addServletMapping("/bug54178ServletA", "bug54178ServletA");
+
+        Bug54178ServletB bug54178ServletB = new Bug54178ServletB();
+        Tomcat.addServlet(ctx, "bug54178ServletB", bug54178ServletB);
+        ctx.addServletMapping("/bug54178ServletB", "bug54178ServletB");
+
+        tomcat.start();
+
+        ByteChunk body = new ByteChunk();
+        int rc = -1;
+
+        try {
+            rc = getUrl("http://localhost:"; + getPort() + "/bug54178ServletA?" 
+
+                    Bug54178ServletA.PARAM_NAME + "=bar",
+                    body, null);
+        } catch (IOException ioe) {
+            // This may happen if test fails. Output the exception in case it 
is
+            // useful and let asserts handle the failure
+            ioe.printStackTrace();
+        }
+
+        assertEquals(HttpServletResponse.SC_OK, rc);
+
+        body.recycle();
+
+        rc = getUrl("http://localhost:"; + getPort() + "/bug54178ServletB",
+                body, null);
+
+        assertEquals(HttpServletResponse.SC_OK, rc);
+        assertEquals("OK", body.toString());
+    }
+
+    private static class Bug54178ServletA extends HttpServlet {
+
+        public static final String PARAM_NAME = "foo";
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        protected void doGet(HttpServletRequest req, HttpServletResponse resp)
+                throws ServletException, IOException {
+
+            req.getParameter(PARAM_NAME);
+            AsyncContext actxt = req.startAsync();
+            actxt.addListener(new Bug54178AsyncListener());
+            actxt.complete();
+        }
+    }
+
+    private static class Bug54178ServletB extends HttpServlet {
+
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        protected void doGet(HttpServletRequest req, HttpServletResponse resp)
+                throws ServletException, IOException {
+
+            resp.setContentType("text/plain");
+            PrintWriter pw = resp.getWriter();
+            String result = req.getParameter(Bug54178ServletA.PARAM_NAME);
+            if (result == null) {
+                pw.write("OK");
+            } else {
+                pw.write("FAIL");
+            }
+        }
+    }
+
+    private static class Bug54178AsyncListener implements AsyncListener {
+
+        @Override
+        public void onComplete(AsyncEvent event) throws IOException {
+            throw new RuntimeException("Testing Bug54178");
+        }
+
+        @Override
+        public void onTimeout(AsyncEvent event) throws IOException {
+            // NO-OP
+        }
+
+        @Override
+        public void onError(AsyncEvent event) throws IOException {
+            // NO-OP
+        }
+
+        @Override
+        public void onStartAsync(AsyncEvent event) throws IOException {
+            // NO-OP
+        }
+    }
 }

Modified: tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml
URL: 
http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml?rev=1471372&r1=1471371&r2=1471372&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml Wed Apr 24 11:43:30 2013
@@ -63,6 +63,11 @@
         (markt) 
       </update>
       <fix>
+        <bug>54178</bug>: Protect against <code>AsyncListener</code>
+        implementations that throw <code>RuntimeException</code>s in response 
to
+        an event. (markt) 
+      </fix>
+      <fix>
         <bug>54851</bug>: When scanning for web fragments, directories without
         any web-fragment.xml should not impact the status of distributable
         element. Patch provided by Trask Stalnaker. (violetagg)



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to