[Bug 62635] Async servlet over HTTP/2 response.flushBuffer() intermittently fails
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
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
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
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
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