yuqi1129 opened a new issue, #13462:
URL: https://github.com/apache/gravitino/issues/13462

   ### Version
   
   main branch
   
   ### Describe what's wrong
   
   
`TestRelationalEntityStoreBatchGetLateFill.testBatchGetRemovesValueWrittenAfterClear`
 hangs forever on `main`, so `./gradlew :core:test` never finishes. The `build 
(17)` job on the merge commit of #13400 (`cd72eac711`) ran `:core:test` for 
1h47m with no further output before being cancelled.
   
   The test injects `store::clearCache` into `CaffeineEntityCache.doPut`, which 
runs inside `SegmentedLock.withLock`. Since #13400, `withLock` holds the 
`globalGate` read lock across its whole critical section and `withGlobalLock` 
takes the write lock. A `ReentrantReadWriteLock` read lock cannot upgrade, so 
the thread blocks on itself. #13400's own javadoc states the rule the test 
breaks:
   
   > Must not be called from inside a `withLock` action on the same instance: 
the read lock cannot upgrade to the write lock, so such a call would deadlock.
   
   Neither PR is wrong alone: #13374 (`3b4778feb3`) added the re-entrant hook 
while `withGlobalLock` took no gate lock, and #13400 (`cd72eac711`) added the 
gate without knowing about the hook. Both were green in isolation.
   
   This is test-only. The sole production callers of `cache.clear()` are 
`EntityCacheChangeLogListener.onEntityChange` (poller thread; `target.clear()` 
runs in the catch block, after `withLock`'s `finally` released the read lock) 
and `RelationalEntityStore.clearCache()`. No production path calls `clear()` 
from inside a `withLock` action.
   
   ### Error message and/or stacktrace
   
   ```
   "Test worker" #1 waiting on condition
      java.lang.Thread.State: WAITING (parking)
           - parking to wait for <0x...> (a 
java.util.concurrent.locks.ReentrantReadWriteLock$FairSync)
           at 
java.util.concurrent.locks.ReentrantReadWriteLock$WriteLock.lock(ReentrantReadWriteLock.java:959)
           at 
org.apache.gravitino.cache.SegmentedLock.withGlobalLock(SegmentedLock.java:245)
           at 
org.apache.gravitino.cache.CaffeineEntityCache.clear(CaffeineEntityCache.java:202)
           at 
org.apache.gravitino.storage.relational.RelationalEntityStore.clearCache(RelationalEntityStore.java:580)
           at 
...TestRelationalEntityStoreBatchGetLateFill$RecordingCache.doPut(TestRelationalEntityStoreBatchGetLateFill.java:254)
           at 
org.apache.gravitino.cache.BaseEntityCache.put(BaseEntityCache.java:120)
           at 
org.apache.gravitino.storage.relational.RelationalEntityStore.lambda$batchGet$3(RelationalEntityStore.java:279)
           at 
org.apache.gravitino.cache.SegmentedLock.withLockAndThrow(SegmentedLock.java:197)
   <-- holds globalGate.readLock
   ```
   
   ### How to reproduce
   
   On `main`:
   
   ```
   ./gradlew :core:test -PskipITs --tests 
'*TestRelationalEntityStoreBatchGetLateFill*'
   ```
   
   It never terminates.
   
   Reverting only `SegmentedLock.java` to `cd72eac711^` (the sole main-code 
file #13400 touched) makes the same 8 tests pass in 36s, which isolates the 
interaction to a single variable.
   
   ### Additional context
   
   The test targets the inner re-check at 
`RelationalEntityStore.batchGet:289-293`. After #13400 a whole-cache clear can 
no longer interleave there at all, so a clear is the wrong way to simulate it. 
A hierarchical or unrelated invalidation still can — it advances the epoch 
without taking the key's lock — and that is the window the re-check genuinely 
defends.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to