HTTP/2 POST: Busy loop after 64k if request not read on server #7821
The test program sends a POST request using HTTP/2 and CURLOPT_READFUNCTION.
If more then 65535 bytes are returned from the read function (in total, after multiple calls of the read function), the test program goes into a busy loop:
The situation is not satisfying: Nothing happens, but 100% CPU is used.
The following debug log is written during the busy loop for libcurl < 7.75:
Not reading the request on the server is only the edge case. When (slowly) reading the request on the server, libcurl sometimes still uses 100% CPU and does nothing.
Same problem when using select() instead of curl_multi_poll().
The problem goes away if using CURL_HTTP_VERSION_1_1:
The problem does not appear if server sends status code >= 300:
The problem does not happen with new Tomcat versions. Most likely the relevant change is in 9.0.18:
Server not reading the buffer is a valid state (at least temporary), libcurl should not busy loop after 64k. Different behaviour for HTTP 1.1 and HTTP/2.
The text was updated successfully, but these errors were encountered:
[I received a URL to a test server setup by @steini2000 and it is most useful!]
I think this is a curl bug that is most noticeable because of a server bug. It turns out that the server doesn't enlarge the remote window, so it drains (thus not allowing more data to get sent) but curl doesn't notice (partly because nghttp2_session_want_write() still returns TRUE in this situation) and then busy-loops around the trying to send.
Fixing the busy-loop (by checking the remote window before waiting for socket writability) doesn't make the operation succeed because the server doesn't enlarge the window so there's no permission to send data.
The fact that this behavior is gone in a newer tomcat release could perhaps be a sign that this bug is fixed already.
PR coming up.
While uploading, check for remote window availability in the getsock function so that we don't wait for a writable socket if no data can be sent. Reported-by: Steini2000 on github Fixes #7821
This seems to fix the busy loop. Thanks!
Newer Tomcat versions always send a RST_STREAM when sending a response without reading all of the request. I have not tested without sending a response. There are a lot of changes in Tomcat regarding the flow control window. But this is not important any more: libcurl is prepared!