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

Program is stuck after calling .text() on Response in WSL 2 #1604

Open
Tobias-Scholz opened this issue Aug 15, 2022 · 4 comments
Open

Program is stuck after calling .text() on Response in WSL 2 #1604

Tobias-Scholz opened this issue Aug 15, 2022 · 4 comments

Comments

@Tobias-Scholz
Copy link

Tobias-Scholz commented Aug 15, 2022

The following issue seems to only be reproducable in WSL 2 (Ubuntu 20.04).

Rust version: 1.63.0

cargo.toml

[dependencies]
reqwest = { version = "0.11", features = ["json"] }
tokio = { version = "1", features = ["full"] }

main.rs

#[tokio::main]
async fn main() {
    println!("Start");

    let url = "https://query1.finance.yahoo.com/v7/finance/download/MSF.DE?period1=0&period2=1660519459&interval=1d&events=history";
    let response = reqwest::get(url).await.unwrap();
    println!("Response finished");

    let response = response.text().await.unwrap();
    println!("{:?}", response); // The program never reaches this point
}

Output:

Start
Response finished

The last println!() never executes and there is no panic.

Further information:

  • The program executes till the end, if the url is replaced with http://www.google.com
  • Printing the raw bytes with .bytes() leads to the same issue
  • The request seems to be successful, as you can print a status code 200 with .status() on the Response struct
  • Could not reproduce this issue on Windows
  • Doing a curl request from WSL 2 does return the correct response (curl --location --request GET 'https://query1.finance.yahoo.com/v7/finance/download/MSF.DE?period1=0&period2=1660519459&interval=1d&events=history')

I also enabled the RUST_LOG=debug logging. This is the only output I am seeing:

[2022-08-15T01:13:51Z DEBUG reqwest::connect] starting new connection: https://query1.finance.yahoo.com/
[2022-08-15T01:13:51Z DEBUG reqwest::async_impl::client] response '200 OK' for https://query1.finance.yahoo.com/v7/finance/download/MSF.DE?period1=0&period2=1660519459&interval=1d&events=history
@seanmonstar
Copy link
Owner

Does the response text ever end? Or does it just download more text forever (normally)? What if you stream the body in chunks?

@Tobias-Scholz
Copy link
Author

Tobias-Scholz commented Aug 15, 2022

@seanmonstar - The response body has a finite length. When doing a curl request, you will get the whole response at once.

I just tried using the .chunks() method and it actually returns some data now.

while let Some(chunk) = response.chunk().await.unwrap() {
    println!("Chunk: {:?}", chunk);
}

println!("finished");

But, it stops execution at around 15% of the data. The last record I can see in the logs is 2010-06-02,14.670000,14.670000,14.670000,14.670000,10.741135, and the rest is missing. Also note that the println!("finished") is not printed so it still gets stuck somewhere.

@ensc
Copy link

ensc commented Aug 22, 2022

I am seeing a similar behaviour; epoll_wait() does not return although
data is available. Smells like a linux kernel bug with edge triggered
epoll (here: kernel 5.18.13).

E.g.

17:07:34.032095 epoll_ctl(5<anon_inode:[eventpoll]>, EPOLL_CTL_ADD, 8<TCP:[138895589]>, {events=EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLET, data={u32=100663298, u64=100663298}}) = 0

17:07:34.034879 writev(8<TCP:[138895589]>, [{iov_base="GET "..., iov_len=122}], 1) = 122
17:07:34.035374 epoll_wait(3<anon_inode:[eventpoll]>, [{events=EPOLLIN|EPOLLOUT, data={u32=100663298, u64=100663298}}], 1024, -1) = 1
17:07:34.035557 recvfrom(8<TCP:[138895589]>, "HTTP"..., 8192, 0, NULL, NULL) = 8192
17:07:34.036444 recvfrom(8<TCP:[138895589]>, "\355Ca\277"..., 16384, 0, NULL, NULL) = 16384
17:07:34.036962 epoll_wait(3<anon_inode:[eventpoll]>, [{events=EPOLLIN|EPOLLOUT, data={u32=100663298, u64=100663298}}, {events=EPOLLIN|EPOLLOUT, data={u32=100663297, u64=100663297}}, {events=EPOLLIN, data={u32=2147483648, u64=2147483648}}], 1024, 2960) = 3

...

17:07:34.042521 recvfrom(7<UDPv6:[138895588]>, "\0\4\0.", ...) = 4
17:07:34.042639 recvfrom(7<UDPv6:[138895588]>, "\0\4\0/", ...) = 4

### A: reqwest chunk() call
17:07:34.042754 recvfrom(8<TCP:[138895589]>, "L\3639C"..., 32768, 0, NULL, NULL) = 8382
17:07:34.043340 recvfrom(7<UDPv6:[138895588]>, "\0\4\0000", ...) = 4
17:07:34.043466 recvfrom(7<UDPv6:[138895588]>, "\0\4\0001", ...) = 4
... more fd 7 related traffic
17:07:34.045128 recvfrom(7<UDPv6:[138895588]>, "\0\4\0?", ...) = 4
17:07:34.045246 recvfrom(7<UDPv6:[138895588]>, "\0\4\0@", ...) = 4

### B: reqwest chunk() call
17:07:34.045341 recvfrom(8<TCP:[138895589]>, 0x5633a0d32de0, 49152, 0, NULL, NULL) = -1 EAGAIN (Resource temporarily unavailable)
17:07:34.045841 epoll_wait(3<anon_inode:[eventpoll]>, [{events=EPOLLOUT, data={u32=100663297, u64=100663297}}], 1024, -1) = 1   ### related to traffic on fd 7
17:07:34.045873 epoll_wait(3<anon_inode:[eventpoll]>,

### ------->  timeout timer (related to fd 7 traffic)

[{events=EPOLLIN|EPOLLOUT, data={u32=100663298, u64=100663298}}], 1024, -1) = 1

### C: reqwest chunk() call
17:07:39.031351 recvfrom(8<TCP:[138895589]>, "\344\217\vB"..., 49152, 0, NULL, NULL) = 32522
17:07:39.032401 recvfrom(7<UDPv6:[138895588]>, "\0\4\0A", ...) = 4
17:07:39.032692 recvfrom(7<UDPv6:[138895588]>, "\0\4\0B", ...) = 4

There is an tokio::time::timeout() of 5 seconds (related to fd 7
traffic) which recovers the reqwest http transfer between "B" and "C".

The other site (busybox httpd) runs on the same host and sends data
with sendfile().

17:50:10.285978 write(1, "HTTP/1.1 2"..., 190) = 190
17:50:10.286033 sendfile(1, 3, [0] => [65536], 9223372036854710272) = 65536
17:50:10.286104 sendfile(1, 3, [65536], 9223372036854710271) = 0
17:50:10.286127 shutdown(1, SHUT_WR) = 0
17:50:10.286157 exit_group(0) = ?

(I ran this later, but relation of timestamps is always the same: server
sends data within <100ms but client goes in a 5 seconds timeout).

@ensc
Copy link

ensc commented Aug 23, 2022

my problem seems to be caused by slirp4netns (rootless containers, rootless-containers/slirp4netns#302)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants