Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sporadic failures/timeout on CI for Arch Linux / HTTP/3 #3088

Open
jcamiel opened this issue Jul 26, 2024 · 1 comment
Open

Sporadic failures/timeout on CI for Arch Linux / HTTP/3 #3088

jcamiel opened this issue Jul 26, 2024 · 1 comment
Labels
bug Something isn't working ci

Comments

@jcamiel
Copy link
Collaborator

jcamiel commented Jul 26, 2024

On our CI, we have sporadic failure when doing a HEAD request to https://google.com on ArchLinux, for HTTP/3.

$ curl --version
curl 8.8.0 (x86_64-pc-linux-gnu) libcurl/8.8.0 OpenSSL/3.3.1 zlib/1.3.1 brotli/1.1.0 zstd/1.5.6 libidn2/2.3.7 libpsl/0.21.5 libssh2/1.11.0 nghttp2/1.62.1 nghttp3/1.4.0
  Release-Date: 2024-05-22
  Protocols: dict file ftp ftps gopher gophers http https imap imaps ipfs ipns mqtt pop3 pop3s rtsp scp sftp smb smbs smtp smtps telnet tftp
  Features: alt-svc AsynchDNS brotli GSS-API HSTS HTTP2 HTTP3 HTTPS-proxy IDN IPv6 Kerberos Largefile libz NTLM PSL SPNEGO SSL threadsafe TLS-SRP UnixSockets zstd
error: HTTP connection
    --> tests_ok/http_version_3_option.hurl:6:6
     |
   6 | HEAD https://google.com/
     |      ^^^^^^^^^^^^^^^^^^ (95) HTTP/3 stream 0 reset by server

Hurl file:

HEAD https://google.com
[Options]
http3: true
HTTP/3 *

curl command:

$ curl --http3 --head https://google.com

Testing many times the curl command, we can't reproduce it.

With a libcurl sample, we can't reproduce the timeout:

int main(int argc, char *argv[])
{
    CURLcode ret;
    CURL *hnd;

    hnd = curl_easy_init();

    curl_easy_reset(hnd);

    curl_easy_setopt(hnd, CURLOPT_BUFFERSIZE, 102400L);
    curl_easy_setopt(hnd, CURLOPT_URL, "https://google.com");
    curl_easy_setopt(hnd, CURLOPT_NOPROGRESS, 1L);
    curl_easy_setopt(hnd, CURLOPT_NOBODY, 1L);
    curl_easy_setopt(hnd, CURLOPT_USERAGENT, "curl/8.8.0");
    curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
    curl_easy_setopt(hnd, CURLOPT_HTTP_VERSION, (long)CURL_HTTP_VERSION_3);
    curl_easy_setopt(hnd, CURLOPT_FILETIME, 1L);
    curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
    curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L);

    curl_easy_setopt(hnd, CURLOPT_COOKIEFILE, "");
    curl_easy_setopt(hnd, CURLOPT_CERTINFO, 1L);
    curl_easy_setopt(hnd, CURLOPT_SSL_VERIFYPEER, 1L);
    curl_easy_setopt(hnd, CURLOPT_SSL_VERIFYHOST, 1L);

    ret = curl_easy_perform(hnd);

    curl_easy_cleanup(hnd);

    return (int)ret;
}

With Easy Rust interface, we can reproduce it:

pub fn perform_head(url: &str) -> Result<(), Error> {
    let mut handle = Easy::new();
    handle.url(url)?;
    handle.nobody(true)?;
    handle.http_version(HttpVersion::V3)?;
    handle.verbose(true)?;
    handle.timeout(Duration::from_secs(20))?;

    let transfer = handle.transfer();
    transfer.perform()?;

    Ok(())
}

With Rust bindings to libcurl, we can't reproduc it:

pub fn perform_head(url: &str) -> Result<(), Error> {
    unsafe {
        curl_sys::curl_global_init(curl_sys::CURL_GLOBAL_ALL);

        let handle = curl_sys::curl_easy_init();

        let url = CString::new(url).unwrap();

        conv(curl_sys::curl_easy_setopt(
            handle,
            curl_sys::CURLOPT_URL,
            url.as_ptr(),
        ))?;
        conv(curl_sys::curl_easy_setopt(
            handle,
            curl_sys::CURLOPT_NOBODY,
            1 as c_long,
        ))?;
        conv(curl_sys::curl_easy_setopt(
            handle,
            curl_sys::CURLOPT_HTTP_VERSION,
            curl_sys::CURL_HTTP_VERSION_3 as c_long,
        ))?;
        conv(curl_sys::curl_easy_setopt(
            handle,
            curl_sys::CURLOPT_VERBOSE,
            1 as c_long,
        ))?;
        conv(curl_sys::curl_easy_setopt(
            handle,
            curl_sys::CURLOPT_TIMEOUT_MS,
            20 * 1000 as c_long,
        ))?;
        conv(curl_sys::curl_easy_perform(handle))?;

        Ok(())
    }
}

fn conv(code: CURLcode) -> Result<(), Error> {
    if code == CURLE_OK {
        Ok(())
    } else {
        Err(Error(code as i32))
    }
}

In my analysis, I've the impression that the Easy curl-rust wrapper do something additional that can trigger this defect.

@jcamiel jcamiel added the bug Something isn't working label Jul 26, 2024
@jcamiel jcamiel changed the title Sporadic failures ON CI for Arch Linux / HTTP/3 Sporadic failures/timeout on CI for Arch Linux / HTTP/3 Jul 26, 2024
@jcamiel jcamiel added the ci label Jul 26, 2024
@jcamiel
Copy link
Collaborator Author

jcamiel commented Jul 26, 2024

Update reproduced with libcurl only with this code:

#include <curl/curl.h>

static CURLcode sslctx_function(CURL *curl, void *sslctx, void *parm) {
    return CURLE_OK;
}

int main(int argc, char *argv[]) {
    CURLcode ret;
    CURL *hnd;

    char *data = "";


    hnd = curl_easy_init();

    curl_easy_reset(hnd);

    curl_easy_setopt(hnd, CURLOPT_URL, "https://google.com");
    curl_easy_setopt(hnd, CURLOPT_TIMEOUT, 20L);
    curl_easy_setopt(hnd, CURLOPT_NOPROGRESS, 1L);
    curl_easy_setopt(hnd, CURLOPT_NOBODY, 1L);
    curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
    curl_easy_setopt(hnd, CURLOPT_HTTP_VERSION, (long)CURL_HTTP_VERSION_3);
    curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
    curl_easy_setopt(hnd, CURLOPT_SSL_CTX_FUNCTION, *sslctx_function);
    curl_easy_setopt(hnd, CURLOPT_SSL_CTX_DATA, data);
    ret = curl_easy_perform(hnd);

    curl_easy_cleanup(hnd);

    return (int)ret;
}

https://github.com/jcamiel/curlhttp3/actions/runs/10113188862/job/27968973290

See mail on libcurl mailing list https://curl.se/mail/lib-2024-07/0035.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working ci
Projects
None yet
Development

No branches or pull requests

1 participant