[Bug 62635] Async servlet over HTTP/2 response.flushBuffer() intermittently fails

2018-08-19 Thread bugzilla
https://bz.apache.org/bugzilla/show_bug.cgi?id=62635

Mark Thomas  changed:

   What|Removed |Added

 Resolution|--- |INVALID
 Status|NEW |RESOLVED

--- Comment #1 from Mark Thomas  ---
flushBuffer() is a blocking I/O call.
It is used when non-blocking I/O was been configured.

This is illegal and the behaviour in this case is unspecified. See section 5.4
of the Servlet spec (bottom of page 5-48 in the final 4.0 spec)


Registering a WriteListener will start non-blocking IO. It is illegal to switch
to the traditional blocking IO at that point. The use of IO related method
calls after this illegal switch to traditional blocking IO produces unspecified
behavior.


I know some containers explicitly attempt to handle this by performing a
non-blocking I/O action rather than the blocking I/O action requested.

This isn't a use case we have implemented in Tomcat. It looks like the thread
performing the blocking flush() enters a wait() and never exists it because the
code that would trigger the exit executes the non-blocking branch rather than
the blocking branch.

I took a look to see if there was a simple way to trigger a non-blocking flush
rather than a blocking flush if applications behave this way. All the solutions
I've found so far are rather more invasive than I'd want to implement to
support what is - after all - not supported by the spec.

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



[Bug 62635] Async servlet over HTTP/2 response.flushBuffer() intermittently fails

2018-08-20 Thread bugzilla
https://bz.apache.org/bugzilla/show_bug.cgi?id=62635

--- Comment #2 from Dapeng Zhang  ---
Thanks Mark for your quick response. It's fair that Tomcat implementation does
not support flushBuffer() in non-blocking I/O mode because it's unspecified.

May I ask some implementation details about Tomcat? Its behavior in the
following scenario will affect whether/how gRPC bi-directional streaming will
be supported.

I assume a buffer is used for the response output stream even for the
non-blocking I/O mode, and the buffer size set by
ServletResponse.setBufferSize() before entering into AsyncContext will still be
honored after getting into non-blocking I/O mode. It seems the buffer will be
automatically flushed if (1) AsyncContext.complete() is called, or (2) the
buffer is full, or (3) prior to the moment when WriteListener.onWritePossible()
is invoked.

However, it seems unspecified in non-blocking I/O mode in the following
scenario:
While the ServletOutputStream is ready I do some write() operations. Suppose
only half of the buffer is used, and suppose the output stream is still ready.
Then I will neither write more data to fully fill the buffer nor call
AsyncContext.complete(), until the client send something in response to my data
in the first half of the buffer. So I need the first half of the buffer to be
drained in order to get something from the client. Will the first half of the
buffer be automatically flushed in this case?

Thanks a lot.

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



[Bug 62635] Async servlet over HTTP/2 response.flushBuffer() intermittently fails

2018-08-20 Thread bugzilla
https://bz.apache.org/bugzilla/show_bug.cgi?id=62635

--- Comment #3 from Mark Thomas  ---
This discussion is heading towards something that would be better held directly
on the dev@ list.

HTTP is not designed for the communication style you describe. The only model
that us guaranteed to work is:
- client writes request
- server reads all of the request
- server writes all of the response
- client reads all of the response

Anything else is going to be fragile depending on exactly what components
(proxies, caches, etc.) site between the client and the server. The sort of
communication you describe would work much better with WebSocket.

Tomcat does maintain an output buffer at the network level and in the situation
you describe it is not flushed.

However..., I've been thinking some more about this and I might have a
non-invasive patch that would allow flushBuffer() to trigger a non-blocking
flush  if non-blocking I/O was in use. Let me dig out the test I wrote for this
and see how it copes...

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



[Bug 62635] Async servlet over HTTP/2 response.flushBuffer() intermittently fails

2018-08-20 Thread bugzilla
https://bz.apache.org/bugzilla/show_bug.cgi?id=62635

--- Comment #4 from Mark Thomas  ---
The patch seems to work so I have committed it. Do let us know how you get on.

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



[Bug 62635] Async servlet over HTTP/2 response.flushBuffer() intermittently fails

2018-08-20 Thread bugzilla
https://bz.apache.org/bugzilla/show_bug.cgi?id=62635

--- Comment #5 from Dapeng Zhang  ---
I tested with the patch. All passed!

I agree that although Servlet 4.0 must support HTTP/2 requests and responses,
and the HTTP/2 protocol allows the HTTP/2 Request/Response Exchange to work in
a full-duplex way easily (
https://httpwg.org/specs/rfc7540.html#rfc.section.8.1 ), it seems not required
that the Servlet server to fully support full-duplex.

I really appreciate the patch, given that it is a not-required (and complex)
feature. Thanks a lot.

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