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

ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-dbcp.git

commit ea6dba616e1447def1470ea200b5c9790dcfc13d
Author: Gary D. Gregory <garydgreg...@gmail.com>
AuthorDate: Mon May 26 10:00:36 2025 -0400

    Fix SpotBugs [ERROR] Medium: Operation on the "fatalSqlExceptionThrown"
    shared variable in "PoolableConnection" class is not atomic
    [org.apache.commons.dbcp2.PoolableConnection]
    AT_NONATOMIC_OPERATIONS_ON_SHARED_VARIABLE
---
 src/changes/changes.xml                                        | 1 +
 src/main/java/org/apache/commons/dbcp2/PoolableConnection.java | 7 ++++---
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 1ee7f6bd..43546b93 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -79,6 +79,7 @@ The <action> type attribute can be add,update,fix,remove.
       <action type="fix" dev="ggregory" due-to="Gary Gregory">Fix SpotBugs 
[ERROR] Medium: Shared primitive variable "closed" in one thread may not yield 
the value of the most recent write from another thread 
[org.apache.commons.dbcp2.cpdsadapter.PooledConnectionImpl] 
AT_STALE_THREAD_WRITE_OF_PRIMITIVE.</action>
       <action type="fix" dev="ggregory" due-to="Gary Gregory">Fix SpotBugs 
[ERROR] Medium: Shared primitive variable "closed" in one thread may not yield 
the value of the most recent write from another thread 
[org.apache.commons.dbcp2.DelegatingStatement] 
AT_STALE_THREAD_WRITE_OF_PRIMITIVE.</action>
       <action type="fix" dev="ggregory" due-to="Gary Gregory">Fix SpotBugs 
[ERROR] Medium: Shared primitive variable "cacheState" in one thread may not 
yield the value of the most recent write from another thread 
[org.apache.commons.dbcp2.DelegatingConnection] 
AT_STALE_THREAD_WRITE_OF_PRIMITIVE.</action>
+      <action type="fix" dev="ggregory" due-to="Gary Gregory">Fix SpotBugs 
[ERROR] Medium: Operation on the "fatalSqlExceptionThrown" shared variable in 
"PoolableConnection" class is not atomic 
[org.apache.commons.dbcp2.PoolableConnection] 
AT_NONATOMIC_OPERATIONS_ON_SHARED_VARIABLE.</action>
       <!-- ADD -->
       <!-- UPDATE -->
       <action type="update" dev="ggregory" due-to="Gary Gregory">Bump 
org.apache.commons:commons-parent from 78 to 81.</action>
diff --git a/src/main/java/org/apache/commons/dbcp2/PoolableConnection.java 
b/src/main/java/org/apache/commons/dbcp2/PoolableConnection.java
index 5c28f930..8653ef98 100644
--- a/src/main/java/org/apache/commons/dbcp2/PoolableConnection.java
+++ b/src/main/java/org/apache/commons/dbcp2/PoolableConnection.java
@@ -24,6 +24,7 @@ import java.sql.SQLException;
 import java.time.Duration;
 import java.util.Collection;
 import java.util.concurrent.Executor;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
 
@@ -68,7 +69,7 @@ public class PoolableConnection extends 
DelegatingConnection<Connection> impleme
      * Indicate that unrecoverable SQLException was thrown when using this 
connection. Such a connection should be
      * considered broken and not pass validation in the future.
      */
-    private boolean fatalSqlExceptionThrown;
+    private AtomicBoolean fatalSqlExceptionThrown = new AtomicBoolean();
 
     /**
      * SQL State codes considered to signal fatal conditions. Overrides the 
defaults in
@@ -259,7 +260,7 @@ public class PoolableConnection extends 
DelegatingConnection<Connection> impleme
 
     @Override
     protected void handleException(final SQLException e) throws SQLException {
-        fatalSqlExceptionThrown |= isFatalException(e);
+        fatalSqlExceptionThrown.compareAndSet(false, isFatalException(e));
         super.handleException(e);
     }
 
@@ -407,7 +408,7 @@ public class PoolableConnection extends 
DelegatingConnection<Connection> impleme
      * @since 2.10.0
      */
     public void validate(final String sql, Duration timeoutDuration) throws 
SQLException {
-        if (fastFailValidation && fatalSqlExceptionThrown) {
+        if (fastFailValidation && fatalSqlExceptionThrown.get()) {
             throw new 
SQLException(Utils.getMessage("poolableConnection.validate.fastFail"));
         }
 

Reply via email to