The deadlock is illustrated best by the following snippet
provided by jianwei zhang who also made the problem analysis
(many thanks!).
```
thread-35
AsyncMessenger::shutdown_connections hold AsyncMessenger::lock std::lock_guard l{lock}
AsyncConnection::stop wait AsyncConnection::lock lock.lock()
thread-3
ProtocolV2::handle_existing_connection hold AsyncConnection::lock std::lock_guard<std::mutex> l(existing->lock)
AsyncMessenger::accept_conn wait AsyncMessenger::lock std::lock_guard l{lock}
```
Fixes: https://tracker.ceph.com/issues/55355
Signed-off-by: Radosław Zarzyński <rzarzyns@redhat.com>
CtPtr ProtocolV2::handle_existing_connection(const AsyncConnectionRef& existing) {
ldout(cct, 20) << __func__ << " existing=" << existing << dendl;
- std::lock_guard<std::mutex> l(existing->lock);
+ std::unique_lock<std::mutex> l(existing->lock);
ProtocolV2 *exproto = dynamic_cast<ProtocolV2 *>(existing->protocol.get());
if (!exproto) {
if (exproto->state == CLOSED) {
ldout(cct, 1) << __func__ << " existing " << existing << " already closed."
<< dendl;
+ l.unlock();
return send_server_ident();
}
<< dendl;
existing->protocol->stop();
existing->dispatch_queue->queue_reset(existing.get());
+ l.unlock();
return send_server_ident();
}