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

            Bug ID: 62614
           Summary: Async servlet over HTTP/2 WriteListener does not work
                    because outputstream.write is hanging even it's ready
           Product: Tomcat 9
           Version: 9.0.10
          Hardware: PC
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P2
         Component: Servlet
          Assignee: dev@tomcat.apache.org
          Reporter: zdap...@google.com
  Target Milestone: -----

Steps to reproduce:

1. Enable HTTP/2 for Tomcat
<Connector port="8080" protocol="HTTP/1.1">
    <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol"/>
</Connector>

2. Deploy the following Servlet

@WebServlet(urlPatterns = {"/asyncwrite"}, asyncSupported = true)
public class AsyncWrite extends HttpServlet {
  @Override
  protected void doGet(HttpServletRequest request, HttpServletResponse
response)
      throws IOException {
    final AsyncContext asyncContext = request.startAsync();

    response.setStatus(HttpServletResponse.SC_OK);
    response.setContentType("application/binary");

    final ServletOutputStream output = response.getOutputStream();
    output.setWriteListener(new WriteListener() {
      int i;
      byte[] bytes = new byte[0x10000];

      @Override
      public void onWritePossible() throws IOException {
        i++;
        System.out.println("onWritePossible called " + i + " times");

        if (i > 3) {
          System.out.println("complete");
          asyncContext.complete();
          return;
        }

        while(output.isReady()) {
          output.write(bytes);
        }

        System.out.println("output.isReady() = " + false);
      }

      @Override
      public void onError(Throwable t) {
        t.printStackTrace();
      }
    });
  }
}

3. Make sure the curl command supports HTTP/2
$ curl --version
curl 7.60.0
Features: AsynchDNS IDN IPv6 Largefile GSS-API Kerberos SPNEGO NTLM NTLM_WB SSL
libz TLS-SRP HTTP2 UnixSockets HTTPS-proxy PSL

4. Run the following curl command over HTTP/1.1
$ curl "http://127.0.0.1:8080/asyncwrite"; -v --output - -w 'received
%{size_download} bytes\n'

No error happens. Check "logs/catalina.out" we can see

onWritePossible called 1 times
output.isReady() = false
onWritePossible called 2 times
output.isReady() = false
onWritePossible called 3 times
output.isReady() = false
onWritePossible called 4 times
complete

5. Run the following curl command over HTTP/2
$ curl  --http2 --http2-prior-knowledge  "http://127.0.0.1:8080/asyncwrite"; -v
--output - -w 'received %{size_download} bytes\n' 

The client hangs. Check "logs/catalina.out" we can only see

onWritePossible called 1 times

Actually output.write(bytes) is hanging.

-- 
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