Blocking connection managers to validate connections after inactivity of more than 2s by default; behavior of async connection managers remains the same
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/BasicHttpClientConnectionManager.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/BasicHttpClientConnectionManager.java
index 6af618f..230c304 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/BasicHttpClientConnectionManager.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/BasicHttpClientConnectionManager.java
@@ -38,6 +38,7 @@
 import org.apache.hc.client5.http.DnsResolver;
 import org.apache.hc.client5.http.HttpRoute;
 import org.apache.hc.client5.http.SchemePortResolver;
+import org.apache.hc.client5.http.impl.ConnPoolSupport;
 import org.apache.hc.client5.http.impl.ConnectionShutdownException;
 import org.apache.hc.client5.http.io.ConnectionEndpoint;
 import org.apache.hc.client5.http.io.HttpClientConnectionManager;
@@ -109,6 +110,8 @@
 
     private final AtomicBoolean closed;
 
+    private volatile TimeValue validateAfterInactivity;
+
     private static Registry<ConnectionSocketFactory> getDefaultRegistry() {
         return RegistryBuilder.<ConnectionSocketFactory>create()
                 .register(URIScheme.HTTP.id, PlainConnectionSocketFactory.getSocketFactory())
@@ -138,6 +141,7 @@
         this.expiry = Long.MAX_VALUE;
         this.socketConfig = SocketConfig.DEFAULT;
         this.closed = new AtomicBoolean(false);
+        this.validateAfterInactivity = TimeValue.ofSeconds(2L);
     }
 
     public BasicHttpClientConnectionManager(
@@ -228,6 +232,26 @@
         }
     }
 
+    private void validate() {
+        final TimeValue validateAfterInactivitySnapshot = validateAfterInactivity;
+        if (this.conn != null
+                && TimeValue.isNonNegative(validateAfterInactivitySnapshot)
+                && updated + validateAfterInactivitySnapshot.toMilliseconds() <= System.currentTimeMillis()) {
+            boolean stale;
+            try {
+                stale = conn.isStale();
+            } catch (final IOException ignore) {
+                stale = true;
+            }
+            if (stale) {
+                if (LOG.isDebugEnabled()) {
+                    LOG.debug("{} connection {} is stale", id, ConnPoolSupport.getId(conn));
+                }
+                closeConnection(CloseMode.GRACEFUL);
+            }
+        }
+    }
+
     synchronized ManagedHttpClientConnection getConnection(final HttpRoute route, final Object state) throws IOException {
         Asserts.check(!this.closed.get(), "Connection manager has been shut down");
         if (LOG.isDebugEnabled()) {
@@ -240,6 +264,7 @@
         this.route = route;
         this.state = state;
         checkExpiry();
+        validate();
         if (this.conn == null) {
             this.conn = this.connFactory.createConnection(null);
         } else {
@@ -365,6 +390,27 @@
         }
     }
 
+    /**
+     * @see #setValidateAfterInactivity(TimeValue)
+     *
+     * @since 5.1
+     */
+    public TimeValue getValidateAfterInactivity() {
+        return validateAfterInactivity;
+    }
+
+    /**
+     * Defines period of inactivity after which persistent connections must
+     * be re-validated prior to being {@link #lease(String, HttpRoute, Object)} leased} to the consumer.
+     * Negative values passed to this method disable connection validation. This check helps
+     * detect connections that have become stale (half-closed) while kept inactive in the pool.
+     *
+     * @since 5.1
+     */
+    public void setValidateAfterInactivity(final TimeValue validateAfterInactivity) {
+        this.validateAfterInactivity = validateAfterInactivity;
+    }
+
     class InternalConnectionEndpoint extends ConnectionEndpoint {
 
         private final HttpRoute route;
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/PoolingHttpClientConnectionManager.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/PoolingHttpClientConnectionManager.java
index 4c8d6d4..13b3998 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/PoolingHttpClientConnectionManager.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/PoolingHttpClientConnectionManager.java
@@ -95,9 +95,6 @@
  * Total time to live (TTL) set at construction time defines maximum life span
  * of persistent connections regardless of their expiration setting. No persistent
  * connection will be re-used past its TTL value.
- * <p>
- * Please note in contrast to 4.x no stale check is employed by default.
- * @see #setValidateAfterInactivity(TimeValue)
  *
  * @since 4.3
  */
@@ -206,6 +203,7 @@
         }
         this.connFactory = connFactory != null ? connFactory : ManagedHttpClientConnectionFactory.INSTANCE;
         this.closed = new AtomicBoolean(false);
+        this.validateAfterInactivity = TimeValue.ofSeconds(2L);
     }
 
     @Internal
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/PoolingHttpClientConnectionManagerBuilder.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/PoolingHttpClientConnectionManagerBuilder.java
index 121127e..2dd506b 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/PoolingHttpClientConnectionManagerBuilder.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/PoolingHttpClientConnectionManagerBuilder.java
@@ -212,7 +212,9 @@
                 schemePortResolver,
                 dnsResolver,
                 connectionFactory);
-        poolingmgr.setValidateAfterInactivity(this.validateAfterInactivity);
+        if (validateAfterInactivity != null) {
+            poolingmgr.setValidateAfterInactivity(validateAfterInactivity);
+        }
         if (defaultSocketConfig != null) {
             poolingmgr.setDefaultSocketConfig(defaultSocketConfig);
         }
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/PoolingAsyncClientConnectionManagerBuilder.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/PoolingAsyncClientConnectionManagerBuilder.java
index cafe7e4..c1dd8ae 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/PoolingAsyncClientConnectionManagerBuilder.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/PoolingAsyncClientConnectionManagerBuilder.java
@@ -201,7 +201,9 @@
                 timeToLive,
                 schemePortResolver,
                 dnsResolver);
-        poolingmgr.setValidateAfterInactivity(this.validateAfterInactivity);
+        if (validateAfterInactivity != null) {
+            poolingmgr.setValidateAfterInactivity(validateAfterInactivity);
+        }
         if (maxConnTotal > 0) {
             poolingmgr.setMaxTotal(maxConnTotal);
         }