By inspecting the code of QuorumCnxManager, I've been able to find a corner case that could cause a RecvWorker thread to hang during shutdown. Here is a summary of how the problem can occur:
1- sendWorkerMap is updated during the execution of softHalt (cnx manager is being shut down);
2- The sender worker that was not shut down during the execution of softHalt will later leave its main loop because the value of the attribute shutdown is true;
3- Leaving the loop due to shutdown evaluating to true does not cause finish() to be called, which must happen to kill its recv worker sibling.
I'm proposing a fix that is quite simple. The correct interleaving to trigger the bug is quite difficult to reproduce, though, so I'm not providing a test.