Skip to content

Reduce deadlock probability of ClientContext.close / TabletLocator.getLocator#6470

Open
dlmarion wants to merge 2 commits into
apache:2.1from
dlmarion:context-locator-deadlock
Open

Reduce deadlock probability of ClientContext.close / TabletLocator.getLocator#6470
dlmarion wants to merge 2 commits into
apache:2.1from
dlmarion:context-locator-deadlock

Conversation

@dlmarion

@dlmarion dlmarion commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Looking at the non-deterministic failures of SessionBlockVerifyIT I found a deadlock between the ClientContext.close and TabletLocator.getLocator methods when there are unclosed Scanners in the client.

JStack found the deadlock at:

Java stack information for the threads listed above:
===================================================
"junit-timeout-thread-4":
	at org.apache.accumulo.core.clientImpl.TabletLocator.disable(TabletLocator.java:134)
	- waiting to lock <0x000000042dbf08e8> (a java.lang.Class for org.apache.accumulo.core.clientImpl.TabletLocator) at
	-  org.apache.accumulo.core.clientImpl.TabletLocator$1.disable(TabletLocator.java:245) at
	-  org.apache.accumulo.core.singletons.SingletonManager.disable(SingletonManager.java:106) at
	-  org.apache.accumulo.core.singletons.SingletonManager$$Lambda/0x00007fbd94325f88.accept(Unknown Source) at
	-  java.util.ArrayList.forEach(java.base@21.0.11/ArrayList.java:1596) at
	-  org.apache.accumulo.core.singletons.SingletonManager.transition(SingletonManager.java:196) at
	-  org.apache.accumulo.core.singletons.SingletonManager.releaseReservation(SingletonManager.java:145)
	- locked <0x000000042dcc4b68> (a java.lang.Class for org.apache.accumulo.core.singletons.SingletonManager) at
	-  org.apache.accumulo.core.singletons.SingletonReservation.close(SingletonReservation.java:50) at
	-  org.apache.accumulo.core.clientImpl.ClientContext.close(ClientContext.java:894)
	- locked <0x000000042d857668> (a org.apache.accumulo.core.clientImpl.ClientContext) at
	-  org.apache.accumulo.test.functional.SessionBlockVerifyIT.run(SessionBlockVerifyIT.java:179)

"pool-2-thread-5":
	at org.apache.accumulo.core.clientImpl.ClientContext.tableZooHelper(ClientContext.java:626)
	- waiting to lock <0x000000042d857668> (a org.apache.accumulo.core.clientImpl.ClientContext) at
	-  org.apache.accumulo.core.clientImpl.ClientContext.getTableState(ClientContext.java:671) at
	-  org.apache.accumulo.core.clientImpl.TabletLocator.getLocator(TabletLocator.java:148)
	- locked <0x000000042dbf08e8> (a java.lang.Class for org.apache.accumulo.core.clientImpl.TabletLocator) at
	-  org.apache.accumulo.core.clientImpl.ThriftScanner.scan(ThriftScanner.java:518) at
	-  org.apache.accumulo.core.clientImpl.ScannerIterator.readBatch(ScannerIterator.java:159)
	- locked <0x000000042d863fb8> (a org.apache.accumulo.core.clientImpl.ThriftScanner$ScanState) at
	-  org.apache.accumulo.core.clientImpl.ScannerIterator.getNextBatch(ScannerIterator.java:177) at
	-  org.apache.accumulo.core.clientImpl.ScannerIterator.hasNext(ScannerIterator.java:109) at
	-  org.apache.accumulo.test.functional.SessionBlockVerifyIT.lambda$0(SessionBlockVerifyIT.java:122) at 
	- org.apache.accumulo.test.functional.SessionBlockVerifyIT$$Lambda/0x00007fbd943acba8.call(Unknown Source)

…deadlock

Looking at the non-deterministic failures of SessionBlockVerifyIT
I found a deadlock between the ClientContext.close and
TabletLocator.getLocator methods where there are unclosed
Scanners in the client.

JStack found the deadlock at:

Java stack information for the threads listed above:
===================================================
"junit-timeout-thread-4":
	at org.apache.accumulo.core.clientImpl.TabletLocator.disable(TabletLocator.java:134)
	- waiting to lock <0x000000042dbf08e8> (a java.lang.Class for org.apache.accumulo.core.clientImpl.TabletLocator)
	at org.apache.accumulo.core.clientImpl.TabletLocator$1.disable(TabletLocator.java:245)
	at org.apache.accumulo.core.singletons.SingletonManager.disable(SingletonManager.java:106)
	at org.apache.accumulo.core.singletons.SingletonManager$$Lambda/0x00007fbd94325f88.accept(Unknown Source)
	at java.util.ArrayList.forEach(java.base@21.0.11/ArrayList.java:1596)
	at org.apache.accumulo.core.singletons.SingletonManager.transition(SingletonManager.java:196)
	at org.apache.accumulo.core.singletons.SingletonManager.releaseReservation(SingletonManager.java:145)
	- locked <0x000000042dcc4b68> (a java.lang.Class for org.apache.accumulo.core.singletons.SingletonManager)
	at org.apache.accumulo.core.singletons.SingletonReservation.close(SingletonReservation.java:50)
	at org.apache.accumulo.core.clientImpl.ClientContext.close(ClientContext.java:894)
	- locked <0x000000042d857668> (a org.apache.accumulo.core.clientImpl.ClientContext)
	at org.apache.accumulo.test.functional.SessionBlockVerifyIT.run(SessionBlockVerifyIT.java:179)

"pool-2-thread-5":
	at org.apache.accumulo.core.clientImpl.ClientContext.tableZooHelper(ClientContext.java:626)
	- waiting to lock <0x000000042d857668> (a org.apache.accumulo.core.clientImpl.ClientContext)
	at org.apache.accumulo.core.clientImpl.ClientContext.getTableState(ClientContext.java:671)
	at org.apache.accumulo.core.clientImpl.TabletLocator.getLocator(TabletLocator.java:148)
	- locked <0x000000042dbf08e8> (a java.lang.Class for org.apache.accumulo.core.clientImpl.TabletLocator)
	at org.apache.accumulo.core.clientImpl.ThriftScanner.scan(ThriftScanner.java:518)
	at org.apache.accumulo.core.clientImpl.ScannerIterator.readBatch(ScannerIterator.java:159)
	- locked <0x000000042d863fb8> (a org.apache.accumulo.core.clientImpl.ThriftScanner$ScanState)
	at org.apache.accumulo.core.clientImpl.ScannerIterator.getNextBatch(ScannerIterator.java:177)
	at org.apache.accumulo.core.clientImpl.ScannerIterator.hasNext(ScannerIterator.java:109)
	at org.apache.accumulo.test.functional.SessionBlockVerifyIT.lambda$0(SessionBlockVerifyIT.java:122)
	at org.apache.accumulo.test.functional.SessionBlockVerifyIT$$Lambda/0x00007fbd943acba8.call(Unknown Source)
@dlmarion dlmarion added this to the 2.1.6 milestone Jul 9, 2026
@dlmarion dlmarion requested a review from ctubbsii July 9, 2026 15:30
@dlmarion dlmarion self-assigned this Jul 9, 2026
@dlmarion dlmarion added blocker This issue blocks any release version labeled on it. bug This issue has been verified to be a bug. labels Jul 9, 2026
Comment thread core/src/main/java/org/apache/accumulo/core/clientImpl/ClientContext.java Outdated
Comment thread core/src/main/java/org/apache/accumulo/core/clientImpl/TabletLocator.java Outdated
@ctubbsii

ctubbsii commented Jul 9, 2026

Copy link
Copy Markdown
Member

It looks like there's several other places where ensureOpen() is called in a synchronized block. It probably shouldn't do that at all. Most of those look like they are doing it for the same reason (lazy initialization). In at least one case, an object is initialized once with a parameter, and subsequent calls ignore the parameter. So, it looks like there's issues with lazy initialization throughout this code related to ensureOpen(). Using separate object monitors for each initialization is a lot of bloat, but a common object monitor to synchronize on for lazy initialization for each may cause another deadlock issue if their initialization uses this (ClientContext) to call into another lazily-initialized method.

It's probably better to use Suppliers.memoize() and to create these suppliers in the constructor to initialize them on first use in their getter when supplier.get() is called. That way, they can be initialized independently without deadlock. The only issue with this is that spotbugs might complain about "this" leaking from a constructor inside the suppliers' lambdas. But those are false positives, since we know "this" isn't actually going to get accessed until the supplier is called the first time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

blocker This issue blocks any release version labeled on it. bug This issue has been verified to be a bug.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants