In ReplicaSetMonitorManager::getMonitorForHost() we iterate over the _monitors map, which contains weak_ptrs as the value, and extract a shared_ptr while holding the class mutex. However, if the owning shared_ptr is freed after we've acquired it here, then the local shared_ptr will be the last reference and destroy the ReplicaSetMonitor that is pointed to. The destructor of that class tries to acquire the same mutex and deadlocks.
This can be fixed by declaring the local shared_ptr outside the lock and freeing it after the lock is released. However, since each iteration of the loop acquires a different shared_ptr, one shared_ptr variable can't be used because it's current value will be released when the next one is assigned to it possibly releasing the last reference.