Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@
import io.grpc.TlsChannelCredentials;
import io.grpc.alts.GoogleDefaultChannelCredentials;
import io.grpc.auth.MoreCallCredentials;
import io.grpc.util.AdvancedTlsX509KeyManager;
import io.grpc.util.AdvancedTlsX509TrustManager;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
Expand All @@ -78,6 +80,7 @@
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
Expand Down Expand Up @@ -556,13 +559,32 @@ ChannelCredentials buildS2AChannelCredentials(
*/
@VisibleForTesting
ChannelCredentials createMtlsToS2AChannelCredentials(
File trustBundle, File privateKey, File certChain) throws IOException {
File trustBundle, File privateKey, File certChain)
throws IOException, GeneralSecurityException {
if (trustBundle == null || privateKey == null || certChain == null) {
return null;
}
AdvancedTlsX509KeyManager keyManager = new AdvancedTlsX509KeyManager();
ScheduledExecutorService keyManagerExecutor = Executors.newSingleThreadScheduledExecutor(
r -> {
Thread t = new Thread(r, "s2a-key-manager-updater");
t.setDaemon(true);
return t;
});

keyManager.updateIdentityCredentials(certChain, privateKey, 1, TimeUnit.HOURS, keyManagerExecutor);
AdvancedTlsX509TrustManager trustManager = AdvancedTlsX509TrustManager.newBuilder().build();
ScheduledExecutorService trustManagerExecutor = Executors.newSingleThreadScheduledExecutor(
r -> {
Thread t = new Thread(r, "s2a-trust-manager-updater");
t.setDaemon(true);
return t;
});
Comment on lines +568 to +582
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

Creating new ScheduledExecutorService instances within createMtlsToS2AChannelCredentials on each call will lead to a resource leak. This method may be called multiple times during the lifetime of a client (e.g., for each channel in a pool, and when channels are refreshed), but the created executors are never shut down. This will cause threads to accumulate over time.

To fix this, you should use shared ScheduledExecutorService instances. A recommended approach is to define them as static final fields in the InstantiatingGrpcChannelProvider class and reuse them here. Since the threads are already configured as daemons, they won't block JVM exit, but sharing them is crucial to prevent resource leaks within a long-running application.

Additionally, the logic for creating the executors is duplicated. You could extract it into a helper method. You might also consider if a single shared executor is sufficient for both the key manager and the trust manager, which would further reduce resource usage.


trustManager.updateTrustCredentials(trustBundle, 1, TimeUnit.HOURS, trustManagerExecutor);
return TlsChannelCredentials.newBuilder()
.keyManager(privateKey, certChain)
.trustManager(trustBundle)
.keyManager(keyManager)
.trustManager(trustManager)
.build();
}

Expand Down
Loading