swiftlang / swift-corelibs-foundation

The Foundation Project, providing core utilities, internationalization, and OS independence
swift.org
Apache License 2.0
5.27k stars 1.13k forks source link

[SR-14591] URLSession seemingly broken on Ubuntu 20.04 #4841

Open kabiroberai opened 3 years ago

kabiroberai commented 3 years ago
Previous ID SR-14591
Radar rdar://problem/77520614
Original Reporter @kabiroberai
Type Bug
Environment macOS 11.2.3 (20D91), Xcode 12.5 (12E262), Docker Desktop 3.3.1 (63152). Docker images: swift:5.4.0-focal, swift:5.4.0-bionic, ubuntu:focal (the latter with a 5.3.2 toolchain manually downloaded from swift.org)
Additional Detail from JIRA | | | |------------------|-----------------| |Votes | 0 | |Component/s | Docker, Foundation | |Labels | Bug | |Assignee | @drexin | |Priority | Medium | md5: 2278a96354f86c6bbe17961ae50891d9

Issue Description:

On Ubuntu 20.04, certain URL requests seem to always time out. For example, the following code (executed with `swift file.swift`) prints "Making request..." followed by "Got data: Optional(214430 bytes)" (or similar) using the swift:5.4.0-bionic Docker image as well as on macOS, but with swift:5.4.0-focal it prints "Making request..." and then times out after several seconds, printing "Got data: nil"

import Foundation
#if os(Linux)
import FoundationNetworking
#endif

let sem = DispatchSemaphore(value: 0)
let url = URL(string: "https://github.com")!
print("Making request...")
URLSession.shared.dataTask(with: url) { data, _, _ in
        defer { sem.signal() }
        print("Got data: \(data as Any)")
}.resume()
sem.wait()

It's also worth noting that `curl https://github.com` works just fine even on swift:5.4.0-focal.

FWIW I'm not sure whether this is Docker-specific or general to all Ubuntu 20.04 setups, as I haven't had the opportunity to test this on a machine running Linux natively, so I've tagged this with Docker for now (alongside Foundation, that is).

typesanitizer commented 3 years ago

@swift-ci create

drexin commented 3 years ago

I am unable to reproduce this. Here's the relevant output:

root@6e45626ecdb9:/tmp# cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=20.04
DISTRIB_CODENAME=focal
DISTRIB_DESCRIPTION="Ubuntu 20.04.2 LTS"
root@6e45626ecdb9:/tmp# cat test.swift
import Foundation
#if os(Linux)
import FoundationNetworking
#endif

let sem = DispatchSemaphore(value: 0)
let url = URL(string: "https://github.com")!
print("Making request...")
URLSession.shared.dataTask(with: url) { data, _, _ in
        defer { sem.signal() }
        print("Got data: \(data as Any)")
}.resume()
sem.wait()
root@6e45626ecdb9:/tmp# swift test.swift
Making request...
Got data: Optional(227191 bytes)

@kabiroberai What options are you running your docker container with?

kabiroberai commented 3 years ago

Huh, github.com is working fine for me too now, but it's started happening for other websites such as https://swift.org. Maybe it's related to SSL certificate expiry dates somehow?

I'm running the docker container with

docker run --cap-add sys_ptrace --security-opt seccomp=unconfined -it --rm swift:5.4-focal bash

FWIW I tried using `export URLSessionDebugLibcurl=true`, and strangely enough the output I recorded back when the issue was occurring for github.com is different from the output for swift.org now.

github.com (May 5th 2021):

root@fcb38d004b4e:/# swift example.swift 
Making request...
2021-05-05 06:32:38.505 swift-frontend[42:2b16c700] [1]                     Trying 140.82.121.3:443...␊
2021-05-05 06:32:38.506 swift-frontend[42:2b16c700] [1]                   TCP_NODELAY set␊
2021-05-05 06:32:38.506 swift-frontend[42:2b16c700] [1]                   Connected to github.com (140.82.121.3) port 443 (#0)␊
2021-05-05 06:32:38.507 swift-frontend[42:2b16c700] [1]                   ALPN, offering h2␊
2021-05-05 06:32:38.507 swift-frontend[42:2b16c700] [1]                   ALPN, offering http/1.1␊
2021-05-05 06:32:38.512 swift-frontend[42:2b16c700] [1]                   successfully set certificate verify locations:␊
2021-05-05 06:32:38.513 swift-frontend[42:2b16c700] [1]                     CAfile: /etc/ssl/certs/ca-certificates.crt␊  CApath: /etc/ssl/certs␊
2021-05-05 06:32:38.513 swift-frontend[42:2b16c700] [1] => Send SSL data  ␖␃␁␂␀
2021-05-05 06:32:38.513 swift-frontend[42:2b16c700] [1]                   TLSv1.3 (OUT), TLS handshake, Client hello (1):␊
2021-05-05 06:32:38.513 swift-frontend[42:2b16c700] [1] => Send SSL data

[long delay]

2021-05-05 06:33:38.458 swift-frontend[42:2b16c700] [1]                   Closing connection 0␊
Got data: nil

swift.org (June 14th 2021):

root@d2c78999ab33:/# swift example.swift 
Making request...
2021-06-14 17:26:03.343 swift-frontend[64:df944700] [1]                     Trying 169.47.73.10:443...␊
2021-06-14 17:26:03.343 swift-frontend[64:df944700] [1]                   TCP_NODELAY set␊

[long delay]

2021-06-14 17:27:03.263 swift-frontend[64:d6130700] [1]                   Closing connection 0␊
Got data: nil
drexin commented 3 years ago

I don't know. I tried https://swift.org as well as a few others and they all work fine.

kabiroberai commented 3 years ago

hmm, I just tested the same setup on a DigitalOcean droplet in the BLR1 region and I was able to reproduce the issue there as well (with swift.org)

kabiroberai commented 3 years ago

I was also able to reproduce the issue on a GitHub Codespaces instance hosted on Azure in Singapore. I tested on GitHub Actions as well (which I'm assuming is hosted somewhere in the US), however I couldn't reproduce the issue there. Seems like it's a regional thing?

drexin commented 3 years ago

Could you print the contents of the `URLResponse?` and `Error?` parameters as well and post them here, please?

kabiroberai commented 3 years ago
Got data: nil. Response: nil. Error: Optional(Error Domain=NSURLErrorDomain Code=-1001 "(null)")

Seems to be kCFURLErrorTimedOut which makes sense since it stalls for exactly 1 minute before calling the completion handler.