You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2019/12/09 17:34:48 UTC

[tomcat] branch master updated: Add a currently disabled test for async timeout with HTTP/2

This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tomcat.git


The following commit(s) were added to refs/heads/master by this push:
     new dcc6ad5  Add a currently disabled test for async timeout with HTTP/2
dcc6ad5 is described below

commit dcc6ad52ad6a3ca53ebc1270b89df9fbc6da2f31
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Mon Dec 9 17:34:10 2019 +0000

    Add a currently disabled test for async timeout with HTTP/2
---
 test/org/apache/coyote/http2/TestAsyncTimeout.java | 142 +++++++++++++++++++++
 1 file changed, 142 insertions(+)

diff --git a/test/org/apache/coyote/http2/TestAsyncTimeout.java b/test/org/apache/coyote/http2/TestAsyncTimeout.java
new file mode 100644
index 0000000..70a5348
--- /dev/null
+++ b/test/org/apache/coyote/http2/TestAsyncTimeout.java
@@ -0,0 +1,142 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.coyote.http2;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.nio.ByteBuffer;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.servlet.AsyncContext;
+import javax.servlet.AsyncEvent;
+import javax.servlet.AsyncListener;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.junit.Assert;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import org.apache.catalina.Context;
+import org.apache.catalina.Wrapper;
+import org.apache.catalina.startup.Tomcat;
+
+public class TestAsyncTimeout extends Http2TestBase {
+
+    @Ignore // Until this HTTP/2 + async timeouts is fixed
+    @Test
+    public void testTimeout() throws Exception {
+        enableHttp2();
+
+        Tomcat tomcat = getTomcatInstance();
+
+        Context ctxt = tomcat.addContext("", null);
+        Tomcat.addServlet(ctxt, "simple", new SimpleServlet());
+        ctxt.addServletMappingDecoded("/simple", "simple");
+        Wrapper w = Tomcat.addServlet(ctxt, "async", new AsyncTimeoutServlet());
+        w.setAsyncSupported(true);
+        ctxt.addServletMappingDecoded("/async", "async");
+        tomcat.start();
+
+        openClientConnection();
+        doHttpUpgrade();
+        sendClientPreface();
+        validateHttp2InitialResponse();
+
+        // Reset connection window size after intial response
+        sendWindowUpdate(0, SimpleServlet.CONTENT_LENGTH);
+
+        output.setTraceBody(true);
+
+        // Send request
+        byte[] frameHeader = new byte[9];
+        ByteBuffer headersPayload = ByteBuffer.allocate(128);
+        buildGetRequest(frameHeader, headersPayload, null, 3, "/async");
+        writeFrame(frameHeader, headersPayload);
+
+        // Headers
+        parser.readFrame(true);
+        // Body
+        parser.readFrame(true);
+
+        // Check that the right number of bytes were received
+        String trace = output.getTrace();
+        Assert.assertTrue(trace, trace.contains("PASS"));
+    }
+
+
+    public static class AsyncTimeoutServlet extends HttpServlet {
+
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        protected void doGet(HttpServletRequest request, HttpServletResponse response)
+                throws IOException {
+
+            final AsyncContext asyncContext = request.startAsync();
+
+            response.setStatus(HttpServletResponse.SC_OK);
+            response.setContentType("text/plain");
+            response.setCharacterEncoding("UTF-8");
+
+            asyncContext.addListener(new AsyncListener() {
+
+                AtomicBoolean ended = new AtomicBoolean(false);
+
+                @Override
+                public void onTimeout(AsyncEvent event) throws IOException {
+                    if (ended.compareAndSet(false, true)) {
+                        PrintWriter pw = event.getAsyncContext().getResponse().getWriter();
+                        pw.write("PASS");
+                        pw.flush();
+                        event.getAsyncContext().complete();
+                    }
+                }
+
+                @Override
+                public void onStartAsync(AsyncEvent event) throws IOException {
+                    // NO-OP
+                }
+
+                @Override
+                public void onError(AsyncEvent event) throws IOException {
+                    // NO-OP
+                }
+
+                @Override
+                public void onComplete(AsyncEvent event) throws IOException {
+                    if (ended.compareAndSet(false, true)) {
+                        PrintWriter pw = event.getAsyncContext().getResponse().getWriter();
+                        pw.write("FAIL");
+                        pw.flush();
+                    }
+                }
+            });
+
+
+            asyncContext.setTimeout(2000);
+
+            try {
+                Thread.sleep(4000);
+            } catch (InterruptedException e) {
+                // Ignore
+            }
+            asyncContext.complete();
+        }
+    }
+}


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


Re: [tomcat] branch master updated: Add a currently disabled test for async timeout with HTTP/2

Posted by Rémy Maucherat <re...@apache.org>.
On Tue, Dec 10, 2019 at 9:06 AM Mark Thomas <ma...@apache.org> wrote:

> On 09/12/2019 21:45, Rémy Maucherat wrote:
> > On Mon, Dec 9, 2019 at 7:59 PM Mark Thomas <markt@apache.org
> > <ma...@apache.org>> wrote:
> >
> >     On 09/12/2019 17:34, markt@apache.org <ma...@apache.org>
> wrote:
> >     > This is an automated email from the ASF dual-hosted git repository.
> >     >
> >     > markt pushed a commit to branch master
> >     > in repository https://gitbox.apache.org/repos/asf/tomcat.git
> >     >
> >     >
> >     > The following commit(s) were added to refs/heads/master by this
> push:
> >     >      new dcc6ad5  Add a currently disabled test for async timeout
> >     with HTTP/2
> >     > dcc6ad5 is described below
> >     >
> >     > commit dcc6ad52ad6a3ca53ebc1270b89df9fbc6da2f31
> >     > Author: Mark Thomas <markt@apache.org <ma...@apache.org>>
> >     > AuthorDate: Mon Dec 9 17:34:10 2019 +0000
> >     >
> >     >     Add a currently disabled test for async timeout with HTTP/2
> >
> >     Note: This test isn't quite right yet. I'll commit the fix once I've
> >     fixed the underlying issue. The issue is proving trickier than I
> thought
> >     it would - mainly because it looks like I'm going to need to make a
> >     bigger change than I really want to. I know what needs to happen, I'm
> >     trying to figure out the best way to make it happen.
> >
> > There's indeed a problem and it's a lot harder than I expected.
> > With async the timeoutAsync goes nowhere as no processor gets added to
> > the waitingProcessors.
> > Without async, the timeout goes to the processor of the connection which
> > isn't much better, it would have to go to the stream which was doing the
> > async request (but it's not processed through the protocol, obviously).
> > Either way it's not going to work :(
>
> After looking at various options I opted to add a reference to the
> Http11Protocol in the Http2Protocol and then added the SocketProcessor
> to the waiting processors.
>
> I have a patch but I need to finish cleaning up the test so it runs
> cleanly.
>

Don't know about your plan there, but I would use an async thread at the
end of the test, otherwise I'm not sure the timeout will be processed:
            asyncContext.setTimeout(2000);
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(10000);
                    } catch (InterruptedException e) {
                        // Ignore
                    }
                    asyncContext.complete();
                }
            }).run();


>
> This has the added benefit that we can reassess the decision to repeat a
> lot of the Http11Procotol config on the Http2Protocol. We could, if we
> wished, just use the settings from the Http11Protocol. Something to
> consider for Tomcat 10 maybe. I'll ask on the users list and see how
> much interest there is in separate settings.
>

That could be a good move.


>
> > Earlier, I wanted to remove the waitingProcessors from AbstractProtocol
> > in favor of some processing in the endpoint. I found out that isn't a
> > very good idea.
> > Maybe instead the actual async timeout processing should be moved one
> > level up (do them in the Catalina adapter, but as usual use a dispatch
> > to do it when they happen). Would that work better ?
>
> I'm not sure. First impression is that it would mean quite a few
> changes. The timeout handling is currently internal to Coyote, this
> would make it part of the Coyote/Catalina API. That doesn't seem quite
> right to me at the moment.
>

No problem, my justification was that the async timeout is not a real IO
timeout but a timeout of the Servlet API, so that's why it could be in
Catalina.

Rémy

Re: [tomcat] branch master updated: Add a currently disabled test for async timeout with HTTP/2

Posted by Mark Thomas <ma...@apache.org>.
On 09/12/2019 21:45, Rémy Maucherat wrote:
> On Mon, Dec 9, 2019 at 7:59 PM Mark Thomas <markt@apache.org
> <ma...@apache.org>> wrote:
> 
>     On 09/12/2019 17:34, markt@apache.org <ma...@apache.org> wrote:
>     > This is an automated email from the ASF dual-hosted git repository.
>     >
>     > markt pushed a commit to branch master
>     > in repository https://gitbox.apache.org/repos/asf/tomcat.git
>     >
>     >
>     > The following commit(s) were added to refs/heads/master by this push:
>     >      new dcc6ad5  Add a currently disabled test for async timeout
>     with HTTP/2
>     > dcc6ad5 is described below
>     >
>     > commit dcc6ad52ad6a3ca53ebc1270b89df9fbc6da2f31
>     > Author: Mark Thomas <markt@apache.org <ma...@apache.org>>
>     > AuthorDate: Mon Dec 9 17:34:10 2019 +0000
>     >
>     >     Add a currently disabled test for async timeout with HTTP/2
> 
>     Note: This test isn't quite right yet. I'll commit the fix once I've
>     fixed the underlying issue. The issue is proving trickier than I thought
>     it would - mainly because it looks like I'm going to need to make a
>     bigger change than I really want to. I know what needs to happen, I'm
>     trying to figure out the best way to make it happen.
> 
> There's indeed a problem and it's a lot harder than I expected.
> With async the timeoutAsync goes nowhere as no processor gets added to
> the waitingProcessors.
> Without async, the timeout goes to the processor of the connection which
> isn't much better, it would have to go to the stream which was doing the
> async request (but it's not processed through the protocol, obviously).
> Either way it's not going to work :(

After looking at various options I opted to add a reference to the
Http11Protocol in the Http2Protocol and then added the SocketProcessor
to the waiting processors.

I have a patch but I need to finish cleaning up the test so it runs cleanly.

This has the added benefit that we can reassess the decision to repeat a
lot of the Http11Procotol config on the Http2Protocol. We could, if we
wished, just use the settings from the Http11Protocol. Something to
consider for Tomcat 10 maybe. I'll ask on the users list and see how
much interest there is in separate settings.

> Earlier, I wanted to remove the waitingProcessors from AbstractProtocol
> in favor of some processing in the endpoint. I found out that isn't a
> very good idea.
> Maybe instead the actual async timeout processing should be moved one
> level up (do them in the Catalina adapter, but as usual use a dispatch
> to do it when they happen). Would that work better ?

I'm not sure. First impression is that it would mean quite a few
changes. The timeout handling is currently internal to Coyote, this
would make it part of the Coyote/Catalina API. That doesn't seem quite
right to me at the moment.

Mark

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


Re: [tomcat] branch master updated: Add a currently disabled test for async timeout with HTTP/2

Posted by Rémy Maucherat <re...@apache.org>.
On Mon, Dec 9, 2019 at 7:59 PM Mark Thomas <ma...@apache.org> wrote:

> On 09/12/2019 17:34, markt@apache.org wrote:
> > This is an automated email from the ASF dual-hosted git repository.
> >
> > markt pushed a commit to branch master
> > in repository https://gitbox.apache.org/repos/asf/tomcat.git
> >
> >
> > The following commit(s) were added to refs/heads/master by this push:
> >      new dcc6ad5  Add a currently disabled test for async timeout with
> HTTP/2
> > dcc6ad5 is described below
> >
> > commit dcc6ad52ad6a3ca53ebc1270b89df9fbc6da2f31
> > Author: Mark Thomas <ma...@apache.org>
> > AuthorDate: Mon Dec 9 17:34:10 2019 +0000
> >
> >     Add a currently disabled test for async timeout with HTTP/2
>
> Note: This test isn't quite right yet. I'll commit the fix once I've
> fixed the underlying issue. The issue is proving trickier than I thought
> it would - mainly because it looks like I'm going to need to make a
> bigger change than I really want to. I know what needs to happen, I'm
> trying to figure out the best way to make it happen.
>
> There's indeed a problem and it's a lot harder than I expected.
With async the timeoutAsync goes nowhere as no processor gets added to the
waitingProcessors.
Without async, the timeout goes to the processor of the connection which
isn't much better, it would have to go to the stream which was doing the
async request (but it's not processed through the protocol, obviously).
Either way it's not going to work :(

Earlier, I wanted to remove the waitingProcessors from AbstractProtocol in
favor of some processing in the endpoint. I found out that isn't a very
good idea.
Maybe instead the actual async timeout processing should be moved one level
up (do them in the Catalina adapter, but as usual use a dispatch to do it
when they happen). Would that work better ?

Rémy

Re: [tomcat] branch master updated: Add a currently disabled test for async timeout with HTTP/2

Posted by Mark Thomas <ma...@apache.org>.
On 09/12/2019 17:34, markt@apache.org wrote:
> This is an automated email from the ASF dual-hosted git repository.
> 
> markt pushed a commit to branch master
> in repository https://gitbox.apache.org/repos/asf/tomcat.git
> 
> 
> The following commit(s) were added to refs/heads/master by this push:
>      new dcc6ad5  Add a currently disabled test for async timeout with HTTP/2
> dcc6ad5 is described below
> 
> commit dcc6ad52ad6a3ca53ebc1270b89df9fbc6da2f31
> Author: Mark Thomas <ma...@apache.org>
> AuthorDate: Mon Dec 9 17:34:10 2019 +0000
> 
>     Add a currently disabled test for async timeout with HTTP/2

Note: This test isn't quite right yet. I'll commit the fix once I've
fixed the underlying issue. The issue is proving trickier than I thought
it would - mainly because it looks like I'm going to need to make a
bigger change than I really want to. I know what needs to happen, I'm
trying to figure out the best way to make it happen.

Mark


> ---
>  test/org/apache/coyote/http2/TestAsyncTimeout.java | 142 +++++++++++++++++++++
>  1 file changed, 142 insertions(+)
> 
> diff --git a/test/org/apache/coyote/http2/TestAsyncTimeout.java b/test/org/apache/coyote/http2/TestAsyncTimeout.java
> new file mode 100644
> index 0000000..70a5348
> --- /dev/null
> +++ b/test/org/apache/coyote/http2/TestAsyncTimeout.java
> @@ -0,0 +1,142 @@
> +/*
> + *  Licensed to the Apache Software Foundation (ASF) under one or more
> + *  contributor license agreements.  See the NOTICE file distributed with
> + *  this work for additional information regarding copyright ownership.
> + *  The ASF licenses this file to You under the Apache License, Version 2.0
> + *  (the "License"); you may not use this file except in compliance with
> + *  the License.  You may obtain a copy of the License at
> + *
> + *      http://www.apache.org/licenses/LICENSE-2.0
> + *
> + *  Unless required by applicable law or agreed to in writing, software
> + *  distributed under the License is distributed on an "AS IS" BASIS,
> + *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> + *  See the License for the specific language governing permissions and
> + *  limitations under the License.
> + */
> +package org.apache.coyote.http2;
> +
> +import java.io.IOException;
> +import java.io.PrintWriter;
> +import java.nio.ByteBuffer;
> +import java.util.concurrent.atomic.AtomicBoolean;
> +
> +import javax.servlet.AsyncContext;
> +import javax.servlet.AsyncEvent;
> +import javax.servlet.AsyncListener;
> +import javax.servlet.http.HttpServlet;
> +import javax.servlet.http.HttpServletRequest;
> +import javax.servlet.http.HttpServletResponse;
> +
> +import org.junit.Assert;
> +import org.junit.Ignore;
> +import org.junit.Test;
> +
> +import org.apache.catalina.Context;
> +import org.apache.catalina.Wrapper;
> +import org.apache.catalina.startup.Tomcat;
> +
> +public class TestAsyncTimeout extends Http2TestBase {
> +
> +    @Ignore // Until this HTTP/2 + async timeouts is fixed
> +    @Test
> +    public void testTimeout() throws Exception {
> +        enableHttp2();
> +
> +        Tomcat tomcat = getTomcatInstance();
> +
> +        Context ctxt = tomcat.addContext("", null);
> +        Tomcat.addServlet(ctxt, "simple", new SimpleServlet());
> +        ctxt.addServletMappingDecoded("/simple", "simple");
> +        Wrapper w = Tomcat.addServlet(ctxt, "async", new AsyncTimeoutServlet());
> +        w.setAsyncSupported(true);
> +        ctxt.addServletMappingDecoded("/async", "async");
> +        tomcat.start();
> +
> +        openClientConnection();
> +        doHttpUpgrade();
> +        sendClientPreface();
> +        validateHttp2InitialResponse();
> +
> +        // Reset connection window size after intial response
> +        sendWindowUpdate(0, SimpleServlet.CONTENT_LENGTH);
> +
> +        output.setTraceBody(true);
> +
> +        // Send request
> +        byte[] frameHeader = new byte[9];
> +        ByteBuffer headersPayload = ByteBuffer.allocate(128);
> +        buildGetRequest(frameHeader, headersPayload, null, 3, "/async");
> +        writeFrame(frameHeader, headersPayload);
> +
> +        // Headers
> +        parser.readFrame(true);
> +        // Body
> +        parser.readFrame(true);
> +
> +        // Check that the right number of bytes were received
> +        String trace = output.getTrace();
> +        Assert.assertTrue(trace, trace.contains("PASS"));
> +    }
> +
> +
> +    public static class AsyncTimeoutServlet extends HttpServlet {
> +
> +        private static final long serialVersionUID = 1L;
> +
> +        @Override
> +        protected void doGet(HttpServletRequest request, HttpServletResponse response)
> +                throws IOException {
> +
> +            final AsyncContext asyncContext = request.startAsync();
> +
> +            response.setStatus(HttpServletResponse.SC_OK);
> +            response.setContentType("text/plain");
> +            response.setCharacterEncoding("UTF-8");
> +
> +            asyncContext.addListener(new AsyncListener() {
> +
> +                AtomicBoolean ended = new AtomicBoolean(false);
> +
> +                @Override
> +                public void onTimeout(AsyncEvent event) throws IOException {
> +                    if (ended.compareAndSet(false, true)) {
> +                        PrintWriter pw = event.getAsyncContext().getResponse().getWriter();
> +                        pw.write("PASS");
> +                        pw.flush();
> +                        event.getAsyncContext().complete();
> +                    }
> +                }
> +
> +                @Override
> +                public void onStartAsync(AsyncEvent event) throws IOException {
> +                    // NO-OP
> +                }
> +
> +                @Override
> +                public void onError(AsyncEvent event) throws IOException {
> +                    // NO-OP
> +                }
> +
> +                @Override
> +                public void onComplete(AsyncEvent event) throws IOException {
> +                    if (ended.compareAndSet(false, true)) {
> +                        PrintWriter pw = event.getAsyncContext().getResponse().getWriter();
> +                        pw.write("FAIL");
> +                        pw.flush();
> +                    }
> +                }
> +            });
> +
> +
> +            asyncContext.setTimeout(2000);
> +
> +            try {
> +                Thread.sleep(4000);
> +            } catch (InterruptedException e) {
> +                // Ignore
> +            }
> +            asyncContext.complete();
> +        }
> +    }
> +}
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: dev-help@tomcat.apache.org
> 


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