]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
ngtcp2: stabilize recv
authorStefan Eissing <stefan@eissing.org>
Thu, 8 Jan 2026 10:19:39 +0000 (11:19 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Thu, 8 Jan 2026 21:36:38 +0000 (22:36 +0100)
When receiving on a stream that already failed or has already been closed,
return the matching error code without touching the connection. In case
the connection shows errors, e.g. the server closed, those errors should
not have impact on an already failed/closed stream.

This might mitigate flakiness in pytest 07_13 where unexpected errors
occur after a successful upload.

Closes #20220

lib/vquic/curl_ngtcp2.c

index 43db734ef78511447f6c5573b7bad25b80d46454..071f38a70d2062228de6582e9180f24237af598b 100644 (file)
@@ -1396,6 +1396,7 @@ static CURLcode cf_ngtcp2_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
   struct cf_call_data save;
   struct pkt_io_ctx pktx;
   CURLcode result = CURLE_OK;
+  int i;
 
   (void)ctx;
   (void)buf;
@@ -1422,21 +1423,29 @@ static CURLcode cf_ngtcp2_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
 
   cf_ngtcp2_ack_stream(cf, data, stream);
 
-  if(cf_progress_ingress(cf, data, &pktx)) {
-    result = CURLE_RECV_ERROR;
-    goto out;
-  }
+  /* first check for results/closed already known without touching
+   * the connection. For an already failed/closed stream, errors on
+   * the connection do not count.
+   * Then handle incoming data and check for failed/closed again.
+   */
+  for(i = 0; i < 2; ++i) {
+    if(stream->xfer_result) {
+      CURL_TRC_CF(data, cf, "[%" PRId64 "] xfer write failed", stream->id);
+      cf_ngtcp2_stream_close(cf, data, stream);
+      result = stream->xfer_result;
+      goto out;
+    }
+    else if(stream->closed) {
+      result = recv_closed_stream(cf, data, stream, pnread);
+      goto out;
+    }
 
-  if(stream->xfer_result) {
-    CURL_TRC_CF(data, cf, "[%" PRId64 "] xfer write failed", stream->id);
-    cf_ngtcp2_stream_close(cf, data, stream);
-    result = stream->xfer_result;
-    goto out;
-  }
-  else if(stream->closed) {
-    result = recv_closed_stream(cf, data, stream, pnread);
-    goto out;
+    if(!i && cf_progress_ingress(cf, data, &pktx)) {
+      result = CURLE_RECV_ERROR;
+      goto out;
+    }
   }
+
   result = CURLE_AGAIN;
 
 out: