Skip to content

Fix deadlock in adapter access tests across named-lock modules - #2033

Open
elharo wants to merge 1 commit into
masterfrom
fix/adapter-test-deadlock
Open

Fix deadlock in adapter access tests across named-lock modules#2033
elharo wants to merge 1 commit into
masterfrom
fix/adapter-test-deadlock

Conversation

@elharo

@elharo elharo commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Complements #2032 by fixing the same deadlock-prone handshake in NamedLockFactoryAdapterTestSupport (used by IpcAdapterIT, IpcAdapterNoForkIT, the hazelcast/redisson adapter ITs, and the LocalReadWriteLock/FileLock/LocalSemaphore adapter tests).

Problem

When both competing threads fail to acquire the lock within the adapter lock wait time (ADAPTER_TIME, default 100 ms, with 1 retry), both Access threads count down the loser latch and then block forever on winner.await(), because the winners latch is never counted down. The tests hang until the JUnit @timeout fires. Under load (e.g. the in-process IPC server thread starved for more than 100 ms) neither acquisition completes in time, so this deadlocks exactly like the factory-level tests in #2032.

Fix

Applied to all four copies of NamedLockFactoryAdapterTestSupport (maven-resolver-named-locks-ipc, -hazelcast, -redisson and maven-resolver-impl):

  • Raise ADAPTER_TIME from 100 ms (500 ms in maven-resolver-impl) to 1000 ms so at least one thread reliably wins even on a loaded machine. Mutual exclusion is still verified: the loser is queued behind the winner on the server and cannot be granted while the winner holds, so its failure is still caused by the winner holding the lock.
  • Bound the winner/loser handshake awaits and the test-side joins and latch awaits, and assert the expected outcome, so a pathological both-lose case fails fast with a clear message instead of hanging for the full @timeout.
  • Bump the @timeout(5) safety nets to @timeout(15) in the hazelcast, redisson and impl copies to leave headroom for the longer legitimate loser path (2 attempts x ADAPTER_TIME + retry wait ~ 2.2 s).
  • maven-resolver-impl: also bound the waits in multipleAcquiresWithALoser, releasedExclusiveAllowAccess and fullyConsumeLockTime; fullyConsumeLockTime's duration assertion is derived from ADAPTER_TIME so it remains valid.

Verification

  • IpcAdapterIT and IpcAdapterNoForkIT: 5 consecutive runs, all passing (9 tests each).
  • maven-resolver-impl: LocalReadWriteLockAdapterTest, FileLockAdapterTest, LocalSemaphoreAdapterTest all pass (13 tests each).
  • maven-resolver-named-locks-hazelcast: HazelcastCPSemaphoreAdapterIT and HazelcastClientCPSemaphoreAdapterIT pass (9 tests each).
  • maven-resolver-named-locks-redisson: compiles; the ITs could not be run locally (they require Docker/testcontainers), but the change is identical in structure to the other three modules.

NamedLockFactoryAdapterTestSupport has the same deadlock-prone
winner/loser handshake as NamedLockFactoryTestSupport: when both
competing threads fail to acquire the lock within the adapter lock
wait time, both count down the loser latch and then block forever on
winner.await(), so the winners latch is never released and the test
hangs until @timeout fires.

Fix the copies in the ipc, hazelcast, redisson and maven-resolver-impl
modules:
- raise ADAPTER_TIME from 100 ms (500 ms in impl) to 1 s so at least
  one thread reliably wins even on a loaded machine; the loser is still
  queued behind the winner, so mutual exclusion is still verified
- bound the winner/loser handshake and the test-side joins and latch
  awaits, and assert the expected outcome, so a pathological both-lose
  case fails fast with a clear message instead of hanging
- bump the @timeout(5) safety nets to @timeout(15) to leave room for
  the longer loser path (2 attempts x ADAPTER_TIME + retry wait)

This complements #2032 for the adapter-level tests.

@gnodet gnodet left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clean, consistent application of the #2032 deadlock fix pattern to all four copies of NamedLockFactoryAdapterTestSupport (IPC, Hazelcast, Redisson, impl). Every unbounded join() and await() is now bounded with 5s timeouts, ADAPTER_TIME raised to 1000ms uniformly, and test-level assertions provide clear diagnostics.

Nice that this covers all four modules — exactly the follow-up we noted in the #2032 review.

This review was generated by an AI agent (Claude Code) and may contain inaccuracies. Please verify all suggestions before applying.

On behalf of gnodet

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants