This is an automated email from the ASF dual-hosted git repository.
dcapwell pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/cassandra-accord.git
The following commit(s) were added to refs/heads/trunk by this push:
new c9ec676c DefaultLocalListeners.remove adds nulls which then leads to
NPE when .clear gets called (#285)
c9ec676c is described below
commit c9ec676c4cd3adced869301a38714c827ac9789e
Author: dcapwell <[email protected]>
AuthorDate: Fri Aug 7 12:28:41 2026 -0700
DefaultLocalListeners.remove adds nulls which then leads to NPE when .clear
gets called (#285)
patch by Alan Wang, C. Scott Andreas, David Capwell; reviewed by C. Scott
Andreas, for CASSANDRA-21551
---
.../src/main/java/accord/impl/DefaultLocalListeners.java | 10 ++++++++--
.../src/test/java/accord/impl/LocalListenersTest.java | 15 +++++++++++++++
2 files changed, 23 insertions(+), 2 deletions(-)
diff --git a/accord-core/src/main/java/accord/impl/DefaultLocalListeners.java
b/accord-core/src/main/java/accord/impl/DefaultLocalListeners.java
index 02bd617b..43fd39cd 100644
--- a/accord-core/src/main/java/accord/impl/DefaultLocalListeners.java
+++ b/accord-core/src/main/java/accord/impl/DefaultLocalListeners.java
@@ -558,8 +558,14 @@ public class DefaultLocalListeners implements
LocalListeners
RegisteredComplexListeners listeners =
complexListeners.remove(key);
if (listeners != null)
{
- for (int i = 0 ; i < listeners.count ; i++)
- listeners.listeners[i].index = -1;
+ if (Invariants.isParanoid()) listeners.checkIntegrity();
+ // On removal listeners contains nulls, so skip
+ for (int i = 0 ; i < listeners.length ; i++)
+ {
+ RegisteredComplexListener l = listeners.listeners[i];
+ if (l != null)
+ l.index = -1;
+ }
}
});
}
diff --git a/accord-core/src/test/java/accord/impl/LocalListenersTest.java
b/accord-core/src/test/java/accord/impl/LocalListenersTest.java
index 8ac0a0bb..9556e6db 100644
--- a/accord-core/src/test/java/accord/impl/LocalListenersTest.java
+++ b/accord-core/src/test/java/accord/impl/LocalListenersTest.java
@@ -466,6 +466,21 @@ public class LocalListenersTest
Assertions.assertEquals(expected, actual);
}
+ @Test
+ public void testClearWithNullHoleFromCancelledComplexListener()
+ {
+ DefaultLocalListeners listeners = new DefaultLocalListeners(null, new
NoOpRemoteListeners(), null);
+ TxnId txnId1 = new TxnId(1, 1, Txn.Kind.Write, Routable.Domain.Key,
new Node.Id(1));
+
+ ComplexListener listener = (safeStore, safeCommand) -> false;
+ LocalListeners.Registered registeredA = listeners.register(txnId1,
listener);
+ listeners.register(txnId1, listener);
+ registeredA.cancel();
+
+ // CASSANDRA-21551: when a listener was removed a null was inserted
and clear didn't have null checks so this would fail
+ Assertions.assertDoesNotThrow(listeners::clear);
+ }
+
@Test
public void testComplexListeners()
{
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]