Skip to content

Conversation

@clintonpi
Copy link

Motivation:

URLSession elusively crashes due to race conditions in OpenSSL <1.1.0 when calling curl_multi_cleanup concurrently on different threads.

Modifications:

  • Add CFURLSessionSSLVersion CFURLSessionSSLVersionInfo(void) for detecting the OpenSSL version in use.
  • Adjust _MultiHandle.deinit to use a process-wide lock to serialize curl_multi_cleanup calls for environments with OpenSSL <1.1.0.

Result:

Prevents the crash while avoiding unnecessary performance overhead for newer OpenSSL versions which are thread-safe.

Testing:

Passing existing tests is sufficient. However, without this patch, the code snippet below crashes about once in 20 runs on Amazon Linux 2

$ curl --version
curl 8.3.0 (aarch64-koji-linux-gnu) libcurl/8.3.0 OpenSSL/1.0.2k-fips zlib/1.2.7 libidn2/2.3.0 libpsl/0.21.5 (+libidn2/2.3.0) libssh2/1.4.3 nghttp2/1.41.0 OpenLDAP/2.4.44
Release-Date: 2023-09-13
...

DispatchQueue.concurrentPerform(iterations: 100) { _ in
    let session: URLSession = URLSession(configuration: URLSessionConfiguration.default)
    DispatchQueue.concurrentPerform(iterations: 100) { _ in
        _ = session
    }
}

Motivation:

`URLSession` elusively crashes due to race conditions in OpenSSL <1.1.0 when calling `curl_multi_cleanup` concurrently on different threads.

Modifications:

- Add `CFURLSessionSSLVersion CFURLSessionSSLVersionInfo(void)` for detecting the OpenSSL version in use.
- Adjust `_MultiHandle.deinit` to use a process-wide lock to serialize `curl_multi_cleanup` calls for environments with OpenSSL <1.1.0.

Result:

Prevents the crash while avoiding unnecessary performance overhead for newer OpenSSL versions which are thread-safe.

Testing:

Passing existing tests is sufficient. However, without this patch, the code snippet below crashes about once in 20 runs on Amazon Linux 2
> $ curl --version
> _curl 8.3.0 (aarch64-koji-linux-gnu) libcurl/8.3.0 OpenSSL/1.0.2k-fips zlib/1.2.7 libidn2/2.3.0 libpsl/0.21.5 (+libidn2/2.3.0) libssh2/1.4.3 nghttp2/1.41.0 OpenLDAP/2.4.44_
> _Release-Date: 2023-09-13_
...
```
DispatchQueue.concurrentPerform(iterations: 100) { _ in
    let session: URLSession = URLSession(configuration: URLSessionConfiguration.default)
    DispatchQueue.concurrentPerform(iterations: 100) { _ in
        _ = session
    }
}
```
@jrflat
Copy link
Contributor

jrflat commented Dec 15, 2025

@swift-ci please test

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

Successfully merging this pull request may close these issues.

2 participants