xds: fix certificate provider closure race during concurrent TLS handshakes (#9248)
Fixes https://github.com/grpc/grpc-go/issues/9015 Root cause for the race: - As part of handling configuration updates, the `clusterimpl` LB policy calls `Close` on its cached certificate providers. The `type` of these certificate providers, as returned by the provider store, is `singleCloseWrappedProvider`, which contains a pointer to a reference counted provider of type `wrappedProvider`. - `singleCloseWrappedProvider.Close()` mutates the internal pointer to an instance of `closedProvider` that always returns an error when asked for key material. - Any concurrent transport creation for a subchannel that had loaded the previous `HandshakeInfo` snapshot and was executing a call to `KeyMaterial` as part of `ClientHandshake` would end up calling `closedProvider.KeyMaterial`, causing the TLS handshake to fail with: `provider instance is closed`. - While `HandshakeInfo` was accessed via an `atomic.Pointer` inside `clusterimpl` and across the load balancer and transport boundaries, the fact that `clusterimpl` was retaining mutable references to state inside the `HandshakeInfo` allowed it to mutate internal in a way that lead to data races. Changes made here: - `HandshakeInfo` now owns the lifetime of the provider instances within it. - It provides APIs to retrieve the `tls.Config` and internally tracks the number of active handshakes - The certificate providers are only closed after the `HandshakeInfo` is closed and all active handshakes have completed. - `clusterimpl` keeps track of the most recent security configuration and suppresses creation of new certificate providers if the config does not change RELEASE NOTES: - xds: Fixed a bug that caused transient handshake failures when TLS handshakes and xDS Cluster updates happened concurrently.
E
Easwar Swaminathan committed
a620350f3eb2090b518063377c7ad859f252e611
Parent: cc23455
Committed by GitHub <noreply@github.com>
on 8/3/2026, 8:04:20 PM