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
Fix close in use certificate providers after double Close()
method call on wrapper object
#7128
base: master
Are you sure you want to change the base?
Conversation
…call on wrapper object Fix errors like: ``` [core][Channel grpc#39 SubChannel grpc#941] grpc: addrConn.createTransport failed to connect to ... Err: connection error: desc = "transport: authentication handshake failed: xds: fetching trusted roots from CertificateProvider failed: provider instance is closed" ```
@bozaro -- Calling Close() feels more like a User error to me and wouldnt categorize this as a bug. I agree that the API could have been better by not providing a Close() method which can be called multiple times, which would cause incorrect accounting wrt That being said, inorder to fix this, I would rather make Provider.Close a grpcsync.OnceFunc. That way we can cleanly assert that a reference can only decrement their reference when calling Close(). |
I think that even if the double The situation when all neighboring uses must be written correctly for your code to work is very fragile. I have found at least two places through which double
I can also add a wrapper in |
@bozaro : Thank you for figuring this out and sending us a PR. There are a few options available to fix this issue:
Instead the approach that we like (which is quite similar to your approach) is as follows:
type singleCloseWrappedProvider struct {
mu sync.Mutex
provider Provider
}
func (s *singleCloseWrappedProvider) KeyMaterial(ctx context.Context) (*KeyMaterial, error) {
s.mu.Lock()
p := s.provider
s.mu.Unlock()
return p.KeyMaterial(ctx)
}
func (s *singleCloseWrappedProvider) Close() {
s.mu.Lock()
s.provider.Close()
s.provider = panickingProvider{}
s.mu.Unlock()
}
type panickingProvider struct{}
func (panickingProvider) Close() {
panic("Close called more than once on certificate provider")
}
func (panickingProvider) KeyMaterial(context.Context) (*KeyMaterial, error) {
return nil, errProviderClosed
}
Please let me know your thoughts on this approach. |
wrappedProvider
add refcounter tocertprovider.Provider
, but there no guards to prevent multipleClose()
call after singleBuild()
call.The situation is complicated by:
certprovider.Provider
implementation don't panic/error on multipleClose()
calls.Fix errors like:
RELEASE NOTES:
xds: fetching trusted roots from CertificateProvider failed: provider instance is closed
error