reqwest: Deadlock on drop of reqwest::blocking::Response sometimes

Sometimes, when a reqwest::blocking::Response is dropped, it appears to deadlock and the drop call never returns. On my setup, it appears to work roughly 70% of the time. Tested on latest master code as of right now.

fn main() {
    for _ in 0..10 {
        may_deadlock();
    }
}

fn may_deadlock() {
    let stream_url = "https://live-bauerse-fm.sharp-stream.com/nrj_instreamtest_se_mp3";

    let mut stream = {
        // setup
        let mut builder = reqwest::blocking::Client::builder();
        // note, I used a proxy:
        // builder = builder.proxy(reqwest::Proxy::all("----").unwrap());
        // get the stream
        builder = builder.connect_timeout(std::time::Duration::from_secs(2));
        builder = builder.timeout(std::time::Duration::from_secs(2));
        let client = builder.build().unwrap();
        let builder = client.get(stream_url);
        builder.send().unwrap()
    };

    println!("ok, reading some data!");
    let mut buffer = [0; 1400];
    use std::io::Read;
    stream.read(&mut buffer).unwrap();
    println!("attempting to drop stream. This will deadlock SOMETIMES...");
    std::mem::drop(stream);
    println!("we get here as expected ~70% of the time");
}

ok, reading some data! attempting to drop stream. This will deadlock SOMETIMES… we get here as expected ~70% of the time ok, reading some data! attempting to drop stream. This will deadlock SOMETIMES… we get here as expected ~70% of the time ok, reading some data! attempting to drop stream. This will deadlock SOMETIMES… we get here as expected ~70% of the time ok, reading some data! attempting to drop stream. This will deadlock SOMETIMES…

then, stuck.

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 2
  • Comments: 21 (7 by maintainers)

Commits related to this issue

Most upvoted comments

Sure, debugging deadlocks is hard.

I just meant to say that exposing such a feature would:

  • allow users that want to protect themselves against them and are willing to pay the runtime cost to do so (this turns deadlocks into panics, so deadlocks could be used to restart things)
  • help people fill better bugreports, because one often discovers a deadlock when the application does not terminate, but I at least often have the doubt of whether “is some work still ongoing” or “is this really a deadlock”. Being able to turn a flag and reproduce with a backtrace is a huge time saver, and allows filling a more informative bug report. Although as you mention, from there to actually finding out what the problem is, the road is long.

What would be the appropriate place to discuss adding such a feature ?

Should hopefully be fixed in the next version of Tokio (0.2.7).

Interesting… I noticed the blocking client is using futures-channel, which may still have a race condition when closing (https://github.com/rust-lang/futures-rs/issues/909). Would you be able to check if https://github.com/seanmonstar/reqwest/pull/748 fixes this for you?