mirror of
https://github.com/ceph/ceph
synced 2025-01-10 21:20:46 +00:00
msgr: queue reset exactly once on any connection
Use the atomic pipe link removal as a signal that we are the one failing the con and use that to queue the reset event. This fixes the case where we have an open, the session gets set up via the handle_accept callback, and then race with another connection and go into wait + close, or just close. In that case, fault() needs to queue a reset event to match the accept. Signed-off-by: Sage Weil <sage@inktank.com>
This commit is contained in:
parent
26e16c008d
commit
de64bc50f2
@ -231,13 +231,15 @@ public:
|
||||
}
|
||||
return !failed;
|
||||
}
|
||||
void clear_pipe(RefCountedObject *old_p) {
|
||||
bool clear_pipe(RefCountedObject *old_p) {
|
||||
if (old_p == pipe) {
|
||||
Mutex::Locker l(lock);
|
||||
pipe->put();
|
||||
pipe = NULL;
|
||||
failed = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void reset_pipe(RefCountedObject *p) {
|
||||
Mutex::Locker l(lock);
|
||||
|
@ -1171,6 +1171,8 @@ void Pipe::fault(bool onread)
|
||||
if (state == STATE_CLOSED ||
|
||||
state == STATE_CLOSING) {
|
||||
ldout(msgr->cct,10) << "fault already closed|closing" << dendl;
|
||||
if (connection_state->clear_pipe(this))
|
||||
msgr->dispatch_queue.queue_reset(connection_state.get());
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1206,9 +1208,8 @@ void Pipe::fault(bool onread)
|
||||
// disconnect from Connection, and mark it failed. future messages
|
||||
// will be dropped.
|
||||
assert(connection_state);
|
||||
connection_state->clear_pipe(this);
|
||||
|
||||
msgr->dispatch_queue.queue_reset(connection_state.get());
|
||||
if (connection_state->clear_pipe(this))
|
||||
msgr->dispatch_queue.queue_reset(connection_state.get());
|
||||
return;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user