From: Fuat Geleri Date: Wed, 22 Nov 2017 22:20:42 +0000 (-0800) Subject: Enable EventBase switching for AsyncSocket even if it has registered events X-Git-Tag: v2017.11.27.00~3 X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=6612bf09e56e819cb76efd0956fdca3dd12ec514;p=folly.git Enable EventBase switching for AsyncSocket even if it has registered events Summary: AsyncSocket will return isDetachable() -> false if there is a read callback set. So, - ignore event registration status - unregister the events when detaching and - register them back when attaching again. Reviewed By: afrind, eduardo-elizondo Differential Revision: D6331787 fbshipit-source-id: fca4e6101f2d5666edbafa09116aa50f34cb084d --- diff --git a/folly/io/async/AsyncSocket.cpp b/folly/io/async/AsyncSocket.cpp index 67c86bf8..1dbaa220 100644 --- a/folly/io/async/AsyncSocket.cpp +++ b/folly/io/async/AsyncSocket.cpp @@ -1434,6 +1434,9 @@ void AsyncSocket::attachEventBase(EventBase* eventBase) { eventBase_ = eventBase; ioHandler_.attachEventBase(eventBase); + + updateEventRegistration(); + writeTimeout_.attachEventBase(eventBase); if (evbChangeCb_) { evbChangeCb_->evbAttached(this); @@ -1448,6 +1451,9 @@ void AsyncSocket::detachEventBase() { eventBase_->dcheckIsInEventBaseThread(); eventBase_ = nullptr; + + ioHandler_.unregisterHandler(); + ioHandler_.detachEventBase(); writeTimeout_.detachEventBase(); if (evbChangeCb_) { @@ -1459,7 +1465,7 @@ bool AsyncSocket::isDetachable() const { DCHECK(eventBase_ != nullptr); eventBase_->dcheckIsInEventBaseThread(); - return !ioHandler_.isHandlerRegistered() && !writeTimeout_.isScheduled(); + return !writeTimeout_.isScheduled(); } void AsyncSocket::cacheAddresses() { diff --git a/folly/io/async/test/AsyncSocketTest2.cpp b/folly/io/async/test/AsyncSocketTest2.cpp index 7e714048..54034e30 100644 --- a/folly/io/async/test/AsyncSocketTest2.cpp +++ b/folly/io/async/test/AsyncSocketTest2.cpp @@ -2857,6 +2857,39 @@ TEST(AsyncSocketTest, EvbCallbacks) { socket->attachEventBase(&evb); } +TEST(AsyncSocketTest, TestEvbDetachWtRegisteredIOHandlers) { + // Start listening on a local port + TestServer server; + + // Connect using a AsyncSocket + EventBase evb; + std::shared_ptr socket = AsyncSocket::newSocket(&evb); + ConnCallback cb; + socket->connect(&cb, server.getAddress(), 30); + + evb.loop(); + + ASSERT_EQ(cb.state, STATE_SUCCEEDED); + EXPECT_LE(0, socket->getConnectTime().count()); + EXPECT_EQ(socket->getConnectTimeout(), std::chrono::milliseconds(30)); + + // After the ioHandlers are registered, still should be able to detach/attach + ReadCallback rcb; + socket->setReadCB(&rcb); + + auto cbEvbChg = std::make_unique(); + InSequence seq; + EXPECT_CALL(*cbEvbChg, evbDetached(socket.get())).Times(1); + EXPECT_CALL(*cbEvbChg, evbAttached(socket.get())).Times(1); + + socket->setEvbChangedCallback(std::move(cbEvbChg)); + EXPECT_TRUE(socket->isDetachable()); + socket->detachEventBase(); + socket->attachEventBase(&evb); + + socket->close(); +} + #ifdef FOLLY_HAVE_MSG_ERRQUEUE /* copied from include/uapi/linux/net_tstamp.h */ /* SO_TIMESTAMPING gets an integer bit field comprised of these values */