hyperium / hyperium/hyper

hyper-util: client connection pool idle timeout does not work as expected

Open
#3,640 5 comments 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

C-bug
Dominant language
Rust
Stars
16.3k
Forks
1.8k
Avg merge
1d 22h
Merged PRs (30d)
14

Description

Version
Latest hyper (1.3.1) & hyper-util (0.1.3)

Platform
Windows11

Description
The issue reproduces in a modified hyper-util client example:

use std::env;

use http_body_util::Empty;
use hyper::Request;
use hyper_util::client::legacy::{connect::HttpConnector, Client};

#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let url = match env::args().nth(1) {
        Some(url) => url,
        None => {
            eprintln!("Usage: client <url>");
            return Ok(());
        }
    };

    // HTTPS requires picking a TLS implementation, so give a better
    // warning if the user tries to request an 'https' URL.
    let url = url.parse::<hyper::Uri>()?;
    if url.scheme_str() != Some("http") {
        eprintln!("This example only works with 'http' URLs.");
        return Ok(());
    }

    let client = Client::builder(hyper_util::rt::TokioExecutor::new())
        .pool_timer(hyper_util::rt::TokioTimer::new())
        .pool_idle_timeout(std::time::Duration::from_secs(1))
        .build(HttpConnector::new());

    let req = Request::builder()
        .uri(url)
        .body(Empty::<bytes::Bytes>::new())?;

    for _ in 0..4 {
        eprintln!("Running request");
        let resp = client.request(req.clone()).await?;

        eprintln!("{:?} {:?}", resp.version(), resp.status());
        eprintln!("{:#?}", resp.headers());

        eprintln!("Waiting 5 seconds");
        _ = tokio::time::sleep(std::time::Duration::from_secs(5)).await;
    }

    eprintln!("Exiting");

    Ok(())
}

Client is configured with idle timeout of 1 sec and the example performs several requests with 5 second delay.
The expectation is that a connection should be dropped from the pool after 1 second during each loop iteration. In practice, the connections start to get dropped only on the second iteration of the loop.

In a real application, this results in connections lingering until a new request is issued.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the modified hyper-util client example and the Client builder calls for pool_timer and pool_idle_timeout. Reproduce the four requests with a five-second delay on Windows 11, then inspect the connection-pool timeout path. Done means the idle connection is dropped after the configured one-second timeout during each loop iteration, with regression coverage for the observed behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
networking
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.