-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Spanner: Spanner.close() does not clean up all resources #5059
Copy link
Copy link
Closed
Labels
api: spannerIssues related to the Spanner API.Issues related to the Spanner API.priority: p1Important issue which blocks shipping the next release. Will be fixed prior to next release.Important issue which blocks shipping the next release. Will be fixed prior to next release.type: bugError or flaw in code with unintended results or allowing sub-optimal usage patterns.Error or flaw in code with unintended results or allowing sub-optimal usage patterns.
Metadata
Metadata
Assignees
Labels
api: spannerIssues related to the Spanner API.Issues related to the Spanner API.priority: p1Important issue which blocks shipping the next release. Will be fixed prior to next release.Important issue which blocks shipping the next release. Will be fixed prior to next release.type: bugError or flaw in code with unintended results or allowing sub-optimal usage patterns.Error or flaw in code with unintended results or allowing sub-optimal usage patterns.
Opening and closing several Spanner instances during the lifetime of an application can cause a thread leak, as the method Spanner.close() does not clean up all threads that are created.
A Spanner instance contains three underlying gRPC stubs:
SpannerStub,InstanceAdminStubandDatabaseAdminStub. In order to prevent these from using the same thread pool for gRPC calls, the stubs are handed a customExecutorProvider. This happens here:google-cloud-java/google-cloud-clients/google-cloud-spanner/src/main/java/com/google/cloud/spanner/spi/v1/GapicSpannerRpc.java
Line 193 in cc04990
The
InstantiatingGrpcChannelProviderwill create the underlying transport channels and assign these executors that are gotten from the aboveExecutorProviderhere: https://github.com/googleapis/gax-java/blob/13564bbe38e5496821e4686ab629181c5bb4ac66/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java#L178This executor is then passed on to a
ManagedChannelBuilder(or actually aNettyChannelBuilderwhich extendsAbstractManagedChannelImplBuilder). This latter builder wraps the executor in aFixedObjectPoolwhich always returns this executor when one is requested from the 'pool', and does nothing when it is returned to the pool. This means that the underlying executor is never shutdown when the transport channel is shutdown.Removing the
setExecutorProvidercall on line 193 ofGapicSpannerRpcsolves the resource leak, but causes the underlying gRPC stubs to use a shared executor for their transport channels, possibly causing race conditions.