cep 59#4953
Conversation
AshenScribe
left a comment
There was a problem hiding this comment.
StorageService.drain() was synchronized on the same monitor as drain(boolean). Pre-CEP-59, drain() called drain(false) directly on the same thread, so reentrancy made this safe. Now drain() hands a callback to gracefulDisconnect(...), which invokes it asynchronously (Netty close-listener or scheduler thread) — so drain(false) can run on a different thread than the one blocked in drain()'s await(). Since that thread still holds the monitor while waiting, drain(false) can never acquire it → deadlock whenever a client is still connected at drain time.
Fix: drop synchronized from drain(), use a dedicated ReentrantLock scoped only to drain() (preserves "one drain at a time"), leave drain(boolean)'s own synchronized untouched.
Cassandra Jira 21191