Skip to content

Core: Fix InMemoryLockManager shared scheduler shutdown#15894

Open
fightBoxing wants to merge 3 commits intoapache:mainfrom
fightBoxing:fix/15861-inmemory-lockmanager-shared-scheduler
Open

Core: Fix InMemoryLockManager shared scheduler shutdown#15894
fightBoxing wants to merge 3 commits intoapache:mainfrom
fightBoxing:fix/15861-inmemory-lockmanager-shared-scheduler

Conversation

@fightBoxing
Copy link
Copy Markdown

Description

Fixes #15861

Problem

BaseLockManager uses a JVM-wide shared static ScheduledExecutorService for heartbeats, but each InMemoryLockManager instance calls close() independently. When multiple managers exist (e.g., in tests or multi-catalog JVM usage), one manager's close() shuts down the shared scheduler via shutdownNow(), causing RejectedExecutionException in other live managers that still need it for heartbeat scheduling.

Root Cause

No reference counting on the shared scheduler. Any single close() call destroys it for all instances.

Fix

  • Added an AtomicInteger reference counter (schedulerRefCount) to BaseLockManager
  • Added a per-instance schedulerInitialized flag to track whether this instance has incremented the ref count
  • In scheduler(): increment ref count on first access per instance
  • In close(): only shutdownNow() the scheduler when the ref count reaches zero (last active manager)

Testing

  • Added testClosingOneManagerDoesNotAffectAnother: creates two managers, closes one, verifies the other can still acquire locks
  • Added testClosingAllManagersShutsDownScheduler: closes all managers, then verifies a new manager can create a fresh scheduler
  • All existing tests pass

Notes

  • The fix is backward compatible - no API changes
  • Thread safety is maintained via synchronized blocks and volatile fields
  • The AtomicInteger counter ensures correct behavior even under concurrent close operations

rockyyin and others added 3 commits January 30, 2026 14:11
Add reference counting to BaseLockManager's shared ScheduledExecutorService
to prevent one manager instance from shutting down the scheduler while
other active instances still need it for heartbeats.

Previously, any single close() call would shutdownNow() the JVM-wide
shared scheduler, causing RejectedExecutionException in other live
managers trying to schedule heartbeats.

The fix tracks per-instance initialization state and uses an AtomicInteger
reference counter. The scheduler is only shut down when the last active
manager closes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Core: InMemoryLockManager can shut down the shared scheduler while another manager is still active

1 participant