This is an automated email from the ASF dual-hosted git repository.

hossman pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/solr.git


The following commit(s) were added to refs/heads/main by this push:
     new 1121d24aff6 SOLR-3696: Fix for LB/Cloud SolrClients that could leak on 
close() if concurrent request failed and triggered zombie server logic
1121d24aff6 is described below

commit 1121d24aff6e6039491d795f9b590841ef513aae
Author: Chris Hostetter <[email protected]>
AuthorDate: Thu Sep 25 10:57:11 2025 -0700

    SOLR-3696: Fix for LB/Cloud SolrClients that could leak on close() if 
concurrent request failed and triggered zombie server logic
---
 solr/CHANGES.txt                                                  | 2 ++
 .../src/java/org/apache/solr/client/solrj/impl/LBSolrClient.java  | 8 ++++++++
 2 files changed, 10 insertions(+)

diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index fb829a39fb9..89c9ff2a3dc 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -309,6 +309,8 @@ Bug Fixes
   and then was used to create future clients (via builder.withHttpClient), 
then redirect processing was wrongly
   disabled on the shared instance. (David Smiley)
 
+* SOLR-3696: Fix for LB/Cloud SolrClients that could leak on close() if 
concurrent request failed and triggered zombie server logic. (hossman)
+
 Dependency Upgrades
 ---------------------
 (No changes)
diff --git 
a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/LBSolrClient.java 
b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/LBSolrClient.java
index ebe6a0ed588..85fadde4ac7 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/LBSolrClient.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/LBSolrClient.java
@@ -86,6 +86,7 @@ public abstract class LBSolrClient extends SolrClient {
   private volatile EndpointWrapper[] aliveServerList = new EndpointWrapper[0];
 
   private volatile ScheduledExecutorService aliveCheckExecutor;
+  private volatile boolean isClosed = false;
 
   protected long aliveCheckIntervalMillis =
       TimeUnit.MILLISECONDS.convert(60, TimeUnit.SECONDS); // 1 minute between 
checks
@@ -574,11 +575,16 @@ public abstract class LBSolrClient extends SolrClient {
     // if it's not null.
     if (aliveCheckExecutor == null) {
       synchronized (this) {
+        if (isClosed) {
+          // must check inside sync block
+          return;
+        }
         if (aliveCheckExecutor == null) {
           log.debug("Starting aliveCheckExecutor for {}", this);
           aliveCheckExecutor =
               Executors.newSingleThreadScheduledExecutor(
                   new SolrNamedThreadFactory("aliveCheckExecutor"));
+          ObjectReleaseTracker.track(aliveCheckExecutor);
           aliveCheckExecutor.scheduleAtFixedRate(
               getAliveCheckRunner(new WeakReference<>(this)),
               this.aliveCheckIntervalMillis,
@@ -825,8 +831,10 @@ public abstract class LBSolrClient extends SolrClient {
   @Override
   public void close() {
     synchronized (this) {
+      isClosed = true;
       if (aliveCheckExecutor != null) {
         ExecutorUtil.shutdownNowAndAwaitTermination(aliveCheckExecutor);
+        ObjectReleaseTracker.release(aliveCheckExecutor);
       }
     }
     ObjectReleaseTracker.release(this);

Reply via email to