Skip to content

HTTP/2 POST: Busy loop after 64k if request not read on server #7821

Closed
@steini2000

Description

@steini2000

The test program sends a POST request using HTTP/2 and CURLOPT_READFUNCTION.
On the server the request is received, but for testing the server does not read the buffer.

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:

  • curl_multi_poll() returns immediately
  • read function is not called
  • no data on the wire

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:
=> Send data, 0 bytes (0x0)
This curl_debug() has been disabled with commit a5bc272.

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:
More then 64k data is sent.

The problem does not appear if server sends status code >= 300:
Info: HTTP error before end of send, stop sending
-> RST_STREAM
If the status code is e.g. 204, problem is there.

The problem does not happen with new Tomcat versions. Most likely the relevant change is in 9.0.18:
When Tomcat writes a final response without reading all of an HTTP/2 request, reset the stream to inform the client that the remaining request body is not required. (markt)
But nevertheless the old Tomcat behaviour is valid and could happen with other HTTP/2 implementations.

Tested versions:
7.68.0 with nghttp2 1.40 on x64
7.79.1 with nghttp2 1.41 on arm
Tomcat 9.0.16, does not happen with 9.0.53

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.

Test programs and log

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions