| 957 | } |
| 958 | |
| 959 | int Socket::WaitAndReset(int32_t expected_nref) { |
| 960 | const uint32_t id_ver = VersionOfVRefId(id()); |
| 961 | uint64_t vref; |
| 962 | // Wait until nref == expected_nref. |
| 963 | while (true) { |
| 964 | // The acquire fence pairs with release fence in Dereference to avoid |
| 965 | // inconsistent states to be seen by others. |
| 966 | vref = versioned_ref(); |
| 967 | if (VersionOfVRef(vref) != id_ver + 1) { |
| 968 | LOG(WARNING) << "SocketId=" << id() << " is already alive or recycled"; |
| 969 | return -1; |
| 970 | } |
| 971 | if (NRefOfVRef(vref) > expected_nref) { |
| 972 | if (bthread_usleep(1000L/*FIXME*/) < 0) { |
| 973 | PLOG_IF(FATAL, errno != ESTOP) << "Fail to sleep"; |
| 974 | return -1; |
| 975 | } |
| 976 | } else if (NRefOfVRef(vref) < expected_nref) { |
| 977 | RPC_VLOG << "SocketId=" << id() |
| 978 | << " was abandoned during health checking"; |
| 979 | return -1; |
| 980 | } else { |
| 981 | // nobody holds a health-checking-related reference, |
| 982 | // so no need to do health checking. |
| 983 | if (!_is_hc_related_ref_held) { |
| 984 | RPC_VLOG << "Nobody holds a health-checking-related reference" |
| 985 | << " for SocketId=" << id(); |
| 986 | return -1; |
| 987 | } |
| 988 | |
| 989 | break; |
| 990 | } |
| 991 | } |
| 992 | |
| 993 | // It's safe to close previous fd (provided expected_nref is correct). |
| 994 | const int prev_fd = _fd.exchange(-1, butil::memory_order_relaxed); |
| 995 | if (ValidFileDescriptor(prev_fd)) { |
| 996 | if (_transport->HasOnEdgeTrigger()) { |
| 997 | _io_event.RemoveConsumer(prev_fd); |
| 998 | } |
| 999 | close(prev_fd); |
| 1000 | if (CreatedByConnect()) { |
| 1001 | g_vars->channel_conn << -1; |
| 1002 | } |
| 1003 | } |
| 1004 | _transport->Reset(expected_nref); |
| 1005 | |
| 1006 | _local_side = butil::EndPoint(); |
| 1007 | if (_ssl_session) { |
| 1008 | SSL_free(_ssl_session); |
| 1009 | _ssl_session = NULL; |
| 1010 | } |
| 1011 | _ssl_state = SSL_UNKNOWN; |
| 1012 | _nevent.store(0, butil::memory_order_relaxed); |
| 1013 | // parsing_context is very likely to be associated with the fd, |
| 1014 | // removing it is a safer choice and required by http2. |
| 1015 | reset_parsing_context(NULL); |
| 1016 | // Must clear _read_buf otehrwise even if the connections is recovered, |
no test coverage detected