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

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


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

commit 47ea29412a0949a769d0b29cb2cc631f8f51d1bb
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
    
    (cherry picked from commit 1121d24aff6e6039491d795f9b590841ef513aae)
---
 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 8af764058bf..1dba30483b2 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -73,6 +73,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 d81ee864e31..d8a82df701b 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
@@ -89,6 +89,7 @@ public abstract class LBSolrClient extends SolrClient {
   private volatile ServerWrapper[] aliveServerList = new ServerWrapper[0];
 
   private volatile ScheduledExecutorService aliveCheckExecutor;
+  private volatile boolean isClosed = false;
 
   protected long aliveCheckIntervalMillis =
       TimeUnit.MILLISECONDS.convert(60, TimeUnit.SECONDS); // 1 minute between 
checks
@@ -602,11 +603,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,
@@ -885,8 +891,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