]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commit
AsyncConnection: Fix deadlock if socket failed when replacing
authorHaomai Wang <haomaiwang@gmail.com>
Wed, 14 Jan 2015 18:32:25 +0000 (02:32 +0800)
committerHaomai Wang <haomaiwang@gmail.com>
Thu, 15 Jan 2015 19:07:14 +0000 (03:07 +0800)
commit7bb7b1ec1e3f8b4141dedc3b88aa2aac476876d4
tree2ca3728c29375f639193e85bd6c1c2f7381928d9
parentbd627e77422340cafff8f61df07874c2db7172f9
AsyncConnection: Fix deadlock if socket failed when replacing

If client reconnect a already mark_down endpoint, server-side will detect
remote reset happen, so it will reset existing connection. Meanwhile,
retry tag is received by client-side connection and it will try to
reconnect. Again, client-side connection will send connect_msg with
connect_seq(1). But it will met server-side connection's connect_seq(0),
it will make server-side reply with reset tag. So this connection will
loop in reset and retry tag.

One solution is that we close server-side connection if connect_seq ==0 and
no message in queue. But it will trigger another problem:
1. client try to connect a already mark_down endpoint
2. client->send_message
3. server-side accept new socket, replace old one and reply retry tag
4. client plus one to connect_seq but socket failure happen
5. server-side connection detected and close because of connect_seq==0 and no
message
6. client reconnect, server-side has no existing connection and met
"connect.connect_seq > 0". So server-side will reply to RESET tag
7. client discard all messages in queue. So we lose a message never delivered

This solution add a new "once_session_reset" flag to indicate whether
"existing" reset. Because server-side's connect_seq is 0 only when it never
successfully or ever session reset. We only need to reply RESET tag if ever
session reset.

Signed-off-by: Haomai Wang <haomaiwang@gmail.com>
src/msg/async/AsyncConnection.cc
src/msg/async/AsyncConnection.h