Skip to content

Intermittent Issues with ReactiveNeo4jClient or Driver not cleaning up resources #2755

@seabamirum

Description

@seabamirum

I have a neo4j/redis REST API that is built with Spring WebFlux and Spring Security. When I enable Blockhound, it's difficult to run my application for very long without encountering an error, sometimes even on sign-in. These errors sometimes lead to deadlocks and application hangs, even without Blockhound running. The problem seems to occur when I run a query with the ReactiveNeo4jClient, and then do something else async after, like logging to a Redis Stream with spring-data-redis. I have been able to reproduce with just two threads hitting "login" ( the success handler logs to a Redis stream). The stack traces suggest it could be something internal, either with the Reactive Client or perhaps the Neo4j driver itself. There are several variants of the error; however all are related to being unable to release a lock on a thread. I will keep working on making a reproducible test case, but wanted to put the info here for now.

Spring-Data-Neo4j 7.1.1
Neo4j Version: Community 5.9
Neo4j Mode: Single instance
Driver Version: 5.9 Java
Operating System: Kubuntu 22.04

Sometimes I just see:

java.lang.IllegalMonitorStateException: attempt to unlock read lock, not locked by current thread

The "null" variant:

java.lang.IllegalMonitorStateException: null
	at java.base/java.util.concurrent.locks.ReentrantReadWriteLock$Sync.tryRelease(ReentrantReadWriteLock.java:372) ~[na:na]
	Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 

The most common, "unsafe park", variant:

2023-06-29T13:19:15.357-04:00 ERROR 8573 --- [oundedElastic-5] a.w.r.e.AbstractErrorWebExceptionHandler : [43ea9a76-6]  500 Server Error for HTTP POST "/login"

reactor.blockhound.BlockingOperationError: Blocking call! jdk.internal.misc.Unsafe#park
	at java.base/jdk.internal.misc.Unsafe.park(Unsafe.java) ~[na:na]
	Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
Error has been observed at the following site(s):
	*__checkpoint ⇢ org.springframework.security.web.server.authentication.AuthenticationWebFilter [DefaultWebFilterChain]
	*__checkpoint ⇢ org.springframework.security.web.server.context.ReactorContextWebFilter [DefaultWebFilterChain]
	*__checkpoint ⇢ org.springframework.security.web.server.header.HttpHeaderWriterWebFilter [DefaultWebFilterChain]
	*__checkpoint ⇢ org.springframework.security.config.web.server.ServerHttpSecurity$ServerWebExchangeReactorContextWebFilter [DefaultWebFilterChain]
	*__checkpoint ⇢ org.springframework.security.web.server.WebFilterChainProxy [DefaultWebFilterChain]
	*__checkpoint ⇢ HTTP POST "/login" [ExceptionHandlingWebHandler]
Original Stack Trace:
		at java.base/jdk.internal.misc.Unsafe.park(Unsafe.java) ~[na:na]
		at java.base/java.util.concurrent.locks.LockSupport.park(LockSupport.java:221) ~[na:na]
		at java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:754) ~[na:na]
		at java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireShared(AbstractQueuedSynchronizer.java:1079) ~[na:na]
		at java.base/java.util.concurrent.locks.ReentrantReadWriteLock$ReadLock.lock(ReentrantReadWriteLock.java:738) ~[na:na]
		at org.neo4j.driver.internal.util.LockUtil.executeWithLock(LockUtil.java:37) ~[neo4j-java-driver-5.9.0.jar:5.9.0-1250b2d94997ae49e5a623c52f61636505185057]
		at org.neo4j.driver.internal.async.pool.ConnectionPoolImpl.getOrCreatePool(ConnectionPoolImpl.java:276) ~[neo4j-java-driver-5.9.0.jar:5.9.0-1250b2d94997ae49e5a623c52f61636505185057]
		at org.neo4j.driver.internal.async.pool.ConnectionPoolImpl.acquire(ConnectionPoolImpl.java:126) ~[neo4j-java-driver-5.9.0.jar:5.9.0-1250b2d94997ae49e5a623c52f61636505185057]
		at org.neo4j.driver.internal.DirectConnectionProvider.acquirePooledConnection(DirectConnectionProvider.java:96) ~[neo4j-java-driver-5.9.0.jar:5.9.0-1250b2d94997ae49e5a623c52f61636505185057]
		at org.neo4j.driver.internal.DirectConnectionProvider.acquireConnection(DirectConnectionProvider.java:52) ~[neo4j-java-driver-5.9.0.jar:5.9.0-1250b2d94997ae49e5a623c52f61636505185057]
		at org.neo4j.driver.internal.async.NetworkSession.lambda$acquireConnection$23(NetworkSession.java:308) ~[neo4j-java-driver-5.9.0.jar:5.9.0-1250b2d94997ae49e5a623c52f61636505185057]
		at java.base/java.util.concurrent.CompletableFuture.uniComposeStage(CompletableFuture.java:1187) ~[na:na]
		at java.base/java.util.concurrent.CompletableFuture.thenCompose(CompletableFuture.java:2341) ~[na:na]
		at java.base/java.util.concurrent.CompletableFuture.thenCompose(CompletableFuture.java:144) ~[na:na]
		at org.neo4j.driver.internal.async.NetworkSession.acquireConnection(NetworkSession.java:303) ~[neo4j-java-driver-5.9.0.jar:5.9.0-1250b2d94997ae49e5a623c52f61636505185057]
		at org.neo4j.driver.internal.async.NetworkSession.lambda$buildResultCursorFactory$17(NetworkSession.java:256) ~[neo4j-java-driver-5.9.0.jar:5.9.0-1250b2d94997ae49e5a623c52f61636505185057]
		at java.base/java.util.concurrent.CompletableFuture.uniComposeStage(CompletableFuture.java:1187) ~[na:na]
		at java.base/java.util.concurrent.CompletableFuture.thenCompose(CompletableFuture.java:2341) ~[na:na]
		at java.base/java.util.concurrent.CompletableFuture.thenCompose(CompletableFuture.java:144) ~[na:na]
		at org.neo4j.driver.internal.async.NetworkSession.buildResultCursorFactory(NetworkSession.java:256) ~[neo4j-java-driver-5.9.0.jar:5.9.0-1250b2d94997ae49e5a623c52f61636505185057]
		at org.neo4j.driver.internal.async.NetworkSession.runRx(NetworkSession.java:124) ~[neo4j-java-driver-5.9.0.jar:5.9.0-1250b2d94997ae49e5a623c52f61636505185057]
		at org.neo4j.driver.internal.reactivestreams.InternalReactiveSession.run(InternalReactiveSession.java:88) ~[neo4j-java-driver-5.9.0.jar:5.9.0-1250b2d94997ae49e5a623c52f61636505185057]
		at org.neo4j.driver.internal.reactivestreams.InternalReactiveSession.run(InternalReactiveSession.java:81) ~[neo4j-java-driver-5.9.0.jar:5.9.0-1250b2d94997ae49e5a623c52f61636505185057]
		at org.neo4j.driver.internal.reactivestreams.BaseReactiveQueryRunner.run(BaseReactiveQueryRunner.java:38) ~[neo4j-java-driver-5.9.0.jar:5.9.0-1250b2d94997ae49e5a623c52f61636505185057]
		at org.neo4j.driver.internal.reactivestreams.BaseReactiveQueryRunner.run(BaseReactiveQueryRunner.java:46) ~[neo4j-java-driver-5.9.0.jar:5.9.0-1250b2d94997ae49e5a623c52f61636505185057]
		at org.springframework.data.neo4j.core.DefaultReactiveNeo4jClient$DelegatingQueryRunner.run(DefaultReactiveNeo4jClient.java:148) ~[spring-data-neo4j-7.1.1.jar:7.1.1]
		at org.springframework.data.neo4j.core.DefaultReactiveNeo4jClient$DefaultRecordFetchSpec.executeWith(DefaultReactiveNeo4jClient.java:418) ~[spring-data-neo4j-7.1.1.jar:7.1.1]
		at org.springframework.data.neo4j.core.DefaultReactiveNeo4jClient$DefaultRecordFetchSpec.lambda$one$5(DefaultReactiveNeo4jClient.java:427) ~[spring-data-neo4j-7.1.1.jar:7.1.1]

Here's another stacktrace I've only seen once:

java.lang.RuntimeException: Async resource cleanup failed after onComplete
	at reactor.core.publisher.FluxUsingWhen$CommitInner.onError(FluxUsingWhen.java:520) ~[reactor-core-3.5.7.jar:3.5.7]
	Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
Error has been observed at the following site(s):
	*__checkpoint ⇢ org.springframework.security.web.server.authentication.AuthenticationWebFilter [DefaultWebFilterChain]
	*__checkpoint ⇢ org.springframework.security.web.server.context.ReactorContextWebFilter [DefaultWebFilterChain]
	*__checkpoint ⇢ org.springframework.security.web.server.header.HttpHeaderWriterWebFilter [DefaultWebFilterChain]
	*__checkpoint ⇢ org.springframework.security.config.web.server.ServerHttpSecurity$ServerWebExchangeReactorContextWebFilter [DefaultWebFilterChain]
	*__checkpoint ⇢ org.springframework.security.web.server.WebFilterChainProxy [DefaultWebFilterChain]
	*__checkpoint ⇢ HTTP POST "/login" [ExceptionHandlingWebHandler]
Original Stack Trace:
		at reactor.core.publisher.FluxUsingWhen$CommitInner.onError(FluxUsingWhen.java:520) ~[reactor-core-3.5.7.jar:3.5.7]
		at reactor.core.publisher.MonoPeekTerminal$MonoTerminalPeekSubscriber.onError(MonoPeekTerminal.java:258) ~[reactor-core-3.5.7.jar:3.5.7]
		at reactor.core.publisher.MonoPeekTerminal$MonoTerminalPeekSubscriber.onComplete(MonoPeekTerminal.java:292) ~[reactor-core-3.5.7.jar:3.5.7]
		at reactor.core.publisher.MonoIgnoreElements$IgnoreElementsSubscriber.onComplete(MonoIgnoreElements.java:89) ~[reactor-core-3.5.7.jar:3.5.7]
		at reactor.core.publisher.MonoIgnoreElements$IgnoreElementsSubscriber.onComplete(MonoIgnoreElements.java:89) ~[reactor-core-3.5.7.jar:3.5.7]
		at reactor.core.publisher.MonoCreate$DefaultMonoSink.success(MonoCreate.java:140) ~[reactor-core-3.5.7.jar:3.5.7]
		at org.neo4j.driver.internal.reactive.RxUtils.lambda$createEmptyPublisher$0(RxUtils.java:44) ~[neo4j-java-driver-5.9.0.jar:5.9.0-1250b2d94997ae49e5a623c52f61636505185057]
		at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:863) ~[na:na]
		at java.base/java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:841) ~[na:na]
		at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510) ~[na:na]
		at java.base/java.util.concurrent.CompletableFuture.complete(CompletableFuture.java:2179) ~[na:na]
		at org.neo4j.driver.internal.handlers.ChannelReleasingResetResponseHandler.lambda$resetCompleted$2(ChannelReleasingResetResponseHandler.java:63) ~[neo4j-java-driver-5.9.0.jar:5.9.0-1250b2d94997ae49e5a623c52f61636505185057]
		at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:863) ~[na:na]
		at java.base/java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:841) ~[na:na]
		at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510) ~[na:na]
		at java.base/java.util.concurrent.CompletableFuture.complete(CompletableFuture.java:2179) ~[na:na]
		at org.neo4j.driver.internal.util.Futures.lambda$asCompletionStage$0(Futures.java:73) ~[neo4j-java-driver-5.9.0.jar:5.9.0-1250b2d94997ae49e5a623c52f61636505185057]
		at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:590) ~[netty-common-4.1.94.Final.jar:4.1.94.Final]
		at io.netty.util.concurrent.DefaultPromise.notifyListenersNow(DefaultPromise.java:557) ~[netty-common-4.1.94.Final.jar:4.1.94.Final]
		at io.netty.util.concurrent.DefaultPromise.access$200(DefaultPromise.java:35) ~[netty-common-4.1.94.Final.jar:4.1.94.Final]
		at io.netty.util.concurrent.DefaultPromise$1.run(DefaultPromise.java:503) ~[netty-common-4.1.94.Final.jar:4.1.94.Final]
		at io.netty.util.concurrent.AbstractEventExecutor.runTask(AbstractEventExecutor.java:174) ~[netty-common-4.1.94.Final.jar:4.1.94.Final]
		at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:167) ~[netty-common-4.1.94.Final.jar:4.1.94.Final]
		at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:470) ~[netty-common-4.1.94.Final.jar:4.1.94.Final]
		at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:569) ~[netty-transport-4.1.94.Final.jar:4.1.94.Final]
		at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997) ~[netty-common-4.1.94.Final.jar:4.1.94.Final]
		at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.94.Final.jar:4.1.94.Final]
		at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.94.Final.jar:4.1.94.Final]
		at java.base/java.lang.Thread.run(Thread.java:1623) ~[na:na]
Caused by: java.lang.IllegalMonitorStateException: null
	at java.base/java.util.concurrent.locks.ReentrantReadWriteLock$Sync.tryRelease(ReentrantReadWriteLock.java:372) ~[na:na]
	at java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1059) ~[na:na]
	at java.base/java.util.concurrent.locks.ReentrantReadWriteLock$WriteLock.unlock(ReentrantReadWriteLock.java:1147) ~[na:na]
	at org.springframework.data.neo4j.core.DefaultReactiveNeo4jClient.lambda$getQueryRunner$2(DefaultReactiveNeo4jClient.java:112) ~[spring-data-neo4j-7.1.1.jar:7.1.1]
	at org.springframework.data.neo4j.core.DefaultReactiveNeo4jClient$DelegatingQueryRunner.lambda$close$0(DefaultReactiveNeo4jClient.java:135) ~[spring-data-neo4j-7.1.1.jar:7.1.1]
	at reactor.core.publisher.MonoPeekTerminal$MonoTerminalPeekSubscriber.onComplete(MonoPeekTerminal.java:289) ~[reactor-core-3.5.7.jar:3.5.7]
	at reactor.core.publisher.MonoIgnoreElements$IgnoreElementsSubscriber.onComplete(MonoIgnoreElements.java:89) ~[reactor-core-3.5.7.jar:3.5.7]
	at reactor.core.publisher.MonoIgnoreElements$IgnoreElementsSubscriber.onComplete(MonoIgnoreElements.java:89) ~[reactor-core-3.5.7.jar:3.5.7]
	at reactor.core.publisher.MonoCreate$DefaultMonoSink.success(MonoCreate.java:140) ~[reactor-core-3.5.7.jar:3.5.7]
	at org.neo4j.driver.internal.reactive.RxUtils.lambda$createEmptyPublisher$0(RxUtils.java:44) ~[neo4j-java-driver-5.9.0.jar:5.9.0-1250b2d94997ae49e5a623c52f61636505185057]
	at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:863) ~[na:na]
	at java.base/java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:841) ~[na:na]
	at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510) ~[na:na]
	at java.base/java.util.concurrent.CompletableFuture.complete(CompletableFuture.java:2179) ~[na:na]
	at org.neo4j.driver.internal.handlers.ChannelReleasingResetResponseHandler.lambda$resetCompleted$2(ChannelReleasingResetResponseHandler.java:63) ~[neo4j-java-driver-5.9.0.jar:5.9.0-1250b2d94997ae49e5a623c52f61636505185057]
	at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:863) ~[na:na]
	at java.base/java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:841) ~[na:na]
	at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510) ~[na:na]
	at java.base/java.util.concurrent.CompletableFuture.complete(CompletableFuture.java:2179) ~[na:na]
	at org.neo4j.driver.internal.util.Futures.lambda$asCompletionStage$0(Futures.java:73) ~[neo4j-java-driver-5.9.0.jar:5.9.0-1250b2d94997ae49e5a623c52f61636505185057]
	at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:590) ~[netty-common-4.1.94.Final.jar:4.1.94.Final]
	at io.netty.util.concurrent.DefaultPromise.notifyListenersNow(DefaultPromise.java:557) ~[netty-common-4.1.94.Final.jar:4.1.94.Final]
	at io.netty.util.concurrent.DefaultPromise.access$200(DefaultPromise.java:35) ~[netty-common-4.1.94.Final.jar:4.1.94.Final]
	at io.netty.util.concurrent.DefaultPromise$1.run(DefaultPromise.java:503) ~[netty-common-4.1.94.Final.jar:4.1.94.Final]
	at io.netty.util.concurrent.AbstractEventExecutor.runTask(AbstractEventExecutor.java:174) ~[netty-common-4.1.94.Final.jar:4.1.94.Final]
	at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:167) ~[netty-common-4.1.94.Final.jar:4.1.94.Final]
	at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:470) ~[netty-common-4.1.94.Final.jar:4.1.94.Final]
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:569) ~[netty-transport-4.1.94.Final.jar:4.1.94.Final]
	at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997) ~[netty-common-4.1.94.Final.jar:4.1.94.Final]
	at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.94.Final.jar:4.1.94.Final]
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.94.Final.jar:4.1.94.Final]
	at java.base/java.lang.Thread.run(Thread.java:1623) ~[na:na]

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions