]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
cf-socket: simulate slow/blocked receives in debug
authorStefan Eissing <stefan@eissing.org>
Thu, 5 Oct 2023 08:05:12 +0000 (10:05 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Sun, 8 Oct 2023 09:04:09 +0000 (11:04 +0200)
add 2 env variables for non-UDP sockets:
1. CURL_DBG_SOCK_RBLOCK: percentage of receive calls that randomly
   should return EAGAIN
2. CURL_DBG_SOCK_RMAX: max amount of bytes read from socket

Closes #12035

lib/cf-socket.c

index effe6e649d1390124dd8af5e618a93f39e7510a5..ce3f9e9437c325fa50d031f9394d44d31b3bf089 100644 (file)
@@ -781,6 +781,8 @@ struct cf_socket_ctx {
 #ifdef DEBUGBUILD
   int wblock_percent;                /* percent of writes doing EAGAIN */
   int wpartial_percent;              /* percent of bytes written in send */
+  int rblock_percent;                /* percent of reads doing EAGAIN */
+  size_t recv_max;                  /* max enforced read size */
 #endif
   BIT(got_first_byte);               /* if first byte was received */
   BIT(accepted);                     /* socket was accepted, not connected */
@@ -811,6 +813,18 @@ static void cf_socket_ctx_init(struct cf_socket_ctx *ctx,
       if(l >= 0 && l <= 100)
         ctx->wpartial_percent = (int)l;
     }
+    p = getenv("CURL_DBG_SOCK_RBLOCK");
+    if(p) {
+      long l = strtol(p, NULL, 10);
+      if(l >= 0 && l <= 100)
+        ctx->rblock_percent = (int)l;
+    }
+    p = getenv("CURL_DBG_SOCK_RMAX");
+    if(p) {
+      long l = strtol(p, NULL, 10);
+      if(l >= 0)
+        ctx->recv_max = (size_t)l;
+    }
   }
 #endif
 }
@@ -1358,6 +1372,27 @@ static ssize_t cf_socket_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
   fdsave = cf->conn->sock[cf->sockindex];
   cf->conn->sock[cf->sockindex] = ctx->sock;
 
+#ifdef DEBUGBUILD
+  /* simulate network blocking/partial reads */
+  if(cf->cft != &Curl_cft_udp && ctx->rblock_percent > 0) {
+    unsigned char c;
+    Curl_rand(data, &c, 1);
+    if(c >= ((100-ctx->rblock_percent)*256/100)) {
+      CURL_TRC_CF(data, cf, "recv(len=%zu) SIMULATE EWOULDBLOCK", len);
+      *err = CURLE_AGAIN;
+      nread = -1;
+      cf->conn->sock[cf->sockindex] = fdsave;
+      return nread;
+    }
+  }
+  if(cf->cft != &Curl_cft_udp && ctx->recv_max && ctx->recv_max < len) {
+    size_t orig_len = len;
+    len = ctx->recv_max;
+    CURL_TRC_CF(data, cf, "recv(len=%zu) SIMULATE max read of %zu bytes",
+                orig_len, len);
+  }
+#endif
+
   if(ctx->buffer_recv && !Curl_bufq_is_empty(&ctx->recvbuf)) {
     CURL_TRC_CF(data, cf, "recv from buffer");
     nread = Curl_bufq_read(&ctx->recvbuf, (unsigned char *)buf, len, err);