int AsyncServerSocket::stopAccepting(int shutdownFlags) { int result = 0; for (auto& handler : sockets_) { VLOG(10) << "AsyncServerSocket::stopAccepting " << this << handler.socket_; } assert(eventBase_ == nullptr || eventBase_->isInEventBaseThread()); // When destroy is called, unregister and close the socket immediately. accepting_ = false; // Close the sockets in reverse order as they were opened to avoid // the condition where another process concurrently tries to open // the same port, succeed to bind the first socket but fails on the // second because it hasn't been closed yet. for (; !sockets_.empty(); sockets_.pop_back()) { auto& handler = sockets_.back(); handler.unregisterHandler(); if (shutdownSocketSet_) { shutdownSocketSet_->close(handler.socket_); } else if (shutdownFlags >= 0) { result = shutdownNoInt(handler.socket_, shutdownFlags); pendingCloseSockets_.push_back(handler.socket_); } else { closeNoInt(handler.socket_); } } // Destroy the backoff timout. This will cancel it if it is running. delete backoffTimeout_; backoffTimeout_ = nullptr; // Close all of the callback queues to notify them that they are being // destroyed. No one should access the AsyncServerSocket any more once // destroy() is called. However, clear out callbacks_ before invoking the // accept callbacks just in case. This will potentially help us detect the // bug if one of the callbacks calls addAcceptCallback() or // removeAcceptCallback(). std::vector<CallbackInfo> callbacksCopy; callbacks_.swap(callbacksCopy); for (std::vector<CallbackInfo>::iterator it = callbacksCopy.begin(); it != callbacksCopy.end(); ++it) { // consumer may not be set if we are running in primary event base if (it->consumer) { DCHECK(it->eventBase); it->consumer->stop(it->eventBase, it->callback); } else { DCHECK(it->callback); it->callback->acceptStopped(); } } return result; }
int AsyncServerSocket::stopAccepting(int shutdownFlags) { int result = 0; for (auto& handler : sockets_) { VLOG(10) << "AsyncServerSocket::stopAccepting " << this << handler.socket_; } assert(eventBase_ == nullptr || eventBase_->isInEventBaseThread()); // When destroy is called, unregister and close the socket immediately accepting_ = false; for (auto& handler : sockets_) { handler.unregisterHandler(); if (shutdownSocketSet_) { shutdownSocketSet_->close(handler.socket_); } else if (shutdownFlags >= 0) { result = shutdownNoInt(handler.socket_, shutdownFlags); pendingCloseSockets_.push_back(handler.socket_); } else { closeNoInt(handler.socket_); } } sockets_.clear(); // Destroy the backoff timout. This will cancel it if it is running. delete backoffTimeout_; backoffTimeout_ = nullptr; // Close all of the callback queues to notify them that they are being // destroyed. No one should access the AsyncServerSocket any more once // destroy() is called. However, clear out callbacks_ before invoking the // accept callbacks just in case. This will potentially help us detect the // bug if one of the callbacks calls addAcceptCallback() or // removeAcceptCallback(). std::vector<CallbackInfo> callbacksCopy; callbacks_.swap(callbacksCopy); for (std::vector<CallbackInfo>::iterator it = callbacksCopy.begin(); it != callbacksCopy.end(); ++it) { it->consumer->stop(it->eventBase, it->callback); } return result; }