From 1bf1f8ed6a28244a90dc7b56823f94c18c9d3aba Mon Sep 17 00:00:00 2001 From: Stefan Eissing Date: Thu, 16 Apr 2026 09:14:58 +0200 Subject: [PATCH] pytest_05_09: increase reliability Test has been flaky due to not waiting for the test server to be listening. On slow CI systems, the started thread is late and the curl command gets a refused connection. Closes #21337 --- lib/cf-socket.c | 18 ++++++++++++------ tests/http/test_05_errors.py | 19 ++++++++++++------- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/lib/cf-socket.c b/lib/cf-socket.c index 796c39075e..b99bcdef55 100644 --- a/lib/cf-socket.c +++ b/lib/cf-socket.c @@ -71,6 +71,7 @@ #include "curlx/strdup.h" #include "system_win32.h" #include "curlx/nonblock.h" +#include "curlx/strcopy.h" #include "curlx/version_win32.h" #include "curlx/strerr.h" #include "curlx/strparse.h" @@ -1305,26 +1306,31 @@ static CURLcode cf_tcp_connect(struct Curl_cfilter *cf, } } else if(rc & CURL_CSELECT_ERR) { + CURL_TRC_CF(data, cf, "poll/select error on fd=%" FMT_SOCKET_T, ctx->sock); (void)verifyconnect(ctx->sock, &ctx->error); result = CURLE_COULDNT_CONNECT; } out: if(result) { + VERBOSE(char buffer[STRERROR_LEN]); + set_local_ip(cf, data); if(ctx->error) { - VERBOSE(char buffer[STRERROR_LEN]); - set_local_ip(cf, data); data->state.os_errno = ctx->error; SET_SOCKERRNO(ctx->error); - infof(data, "connect to %s port %u from %s port %d failed: %s", - ctx->ip.remote_ip, ctx->ip.remote_port, - ctx->ip.local_ip, ctx->ip.local_port, - curlx_strerror(ctx->error, buffer, sizeof(buffer))); + VERBOSE(curlx_strerror(ctx->error, buffer, sizeof(buffer))); + } + else { + VERBOSE(curlx_strcopy(buffer, sizeof(buffer), STRCONST("peer closed"))); } if(ctx->sock != CURL_SOCKET_BAD) { socket_close(data, cf->conn, TRUE, ctx->sock); ctx->sock = CURL_SOCKET_BAD; } + infof(data, "connect to %s port %u from %s port %d failed: %s", + ctx->ip.remote_ip, ctx->ip.remote_port, + ctx->ip.local_ip, ctx->ip.local_port, + curlx_strerror(ctx->error, buffer, sizeof(buffer))); *done = FALSE; } return result; diff --git a/tests/http/test_05_errors.py b/tests/http/test_05_errors.py index c50310404f..4e5f552412 100644 --- a/tests/http/test_05_errors.py +++ b/tests/http/test_05_errors.py @@ -28,6 +28,7 @@ import logging import os import socket import threading +import time import pytest from testenv import CurlClient, Env @@ -183,7 +184,7 @@ class TestErrors: assert r.stats[0]['num_retries'] == 0, f'{r}' # Server closes the connection immediately after accept, - def test_05_09_handshake_eof(self, env: Env, httpd, nghttpx): + def test_05_09_handshake_eof(self, env: Env): with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server: server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) server.bind(('127.0.0.1', 0)) @@ -194,6 +195,7 @@ class TestErrors: def accept_and_close(): try: conn, _ = server.accept() + conn.recv(1) # wait for ClientHello conn.close() except Exception: pass @@ -201,14 +203,17 @@ class TestErrors: t = threading.Thread(target=accept_and_close) t.start() - curl = CurlClient(env=env, timeout=5) + run_env = os.environ.copy() + run_env['CURL_DEBUG'] = 'all' + curl = CurlClient(env=env, timeout=env.test_timeout, run_env=run_env) url = f'https://127.0.0.1:{port}/' - r = curl.run_direct(args=[url, '--insecure']) + r = curl.run_direct(args=[url, '--insecure', '-v']) - t.join(timeout=2) + t.join(timeout=10) # We expect an error code, not success (0) and not timeout (-1) - # Expected error code is: + # Expected error codes are: # - CURLE_SSL_CONNECT_ERROR (35) - common for handshake failures - assert r.exit_code == 35, \ - f'Expected error 35, got {r.exit_code}\n{r.dump_logs()}' + # - CURLE_RECV_ERROR (56) - some TLS backends fail with that + assert r.exit_code in [35, 56], \ + f'unexpected error {r.exit_code}\n{r.dump_logs()}'