Commit 5451eeae authored by Yang Chi's avatar Yang Chi Committed by Facebook Github Bot 4

Set bufferCallback_ back to nullptr upon HTTPSession shutdown

Summary: AsyncSocket::handleWrite may trigger HTTPSession::onWriteSuccess which may totally delete the HTTPSession. AsyncSocket::handleWrite also calls bufferCallback_->onEgressBufferCleared(). That bufferCallback_ is the HTTPSession. So in this diff resets bufferCallback_ to nullptr upon HTTPSession shutdown. afrind had a suggestion of adding a DestructorGuard in AsyncSocket::handleWrite. But i don't know DestructorGuard that well. I think it will keep AsyncSocket from being deleted but not the HTTPSession? Or maybe I can DestructorGuard dg(bufferCallback_) ?

Reviewed By: afrind

Differential Revision: D3311058

fbshipit-source-id: cdb5fcbd53837a3effbc096eab87fca4e5d17291
parent 8eaa9657
......@@ -1430,6 +1430,8 @@ void AsyncSocket::handleRead() noexcept {
void AsyncSocket::handleWrite() noexcept {
VLOG(5) << "AsyncSocket::handleWrite() this=" << this << ", fd=" << fd_
<< ", state=" << state_;
DestructorGuard dg(this);
if (state_ == StateEnum::CONNECTING) {
handleConnect();
return;
......
......@@ -2280,3 +2280,34 @@ TEST(AsyncSocketTest, BufferTest) {
ASSERT_TRUE(socket->isClosedBySelf());
ASSERT_FALSE(socket->isClosedByPeer());
}
TEST(AsyncSocketTest, BufferCallbackKill) {
TestServer server;
EventBase evb;
AsyncSocket::OptionMap option{{{SOL_SOCKET, SO_SNDBUF}, 128}};
std::shared_ptr<AsyncSocket> socket = AsyncSocket::newSocket(&evb);
ConnCallback ccb;
socket->connect(&ccb, server.getAddress(), 30, option);
evb.loopOnce();
char buf[100 * 1024];
memset(buf, 'c', sizeof(buf));
BufferCallback* bcb = new BufferCallback;
socket->setBufferCallback(bcb);
WriteCallback wcb;
wcb.successCallback = [&] {
ASSERT_TRUE(socket.unique());
socket.reset();
};
// This will trigger AsyncSocket::handleWrite,
// which calls WriteCallback::writeSuccess,
// which calls wcb.successCallback above,
// which tries to delete socket
// Then, the socket will also try to use this BufferCallback
// And that should crash us, if there is no DestructorGuard on the stack
socket->write(&wcb, buf, sizeof(buf), WriteFlags::NONE);
evb.loop();
CHECK_EQ(ccb.state, STATE_SUCCEEDED);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment