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()}'