Skip to content

Commit 3ddca84

Browse files
Prevent TcpClient::removeConnection call on deleted TcpClient instance. (#197)
1 parent a01b3b4 commit 3ddca84

File tree

2 files changed

+38
-19
lines changed

2 files changed

+38
-19
lines changed

trantor/net/TcpClient.cc

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -82,25 +82,25 @@ TcpClient::~TcpClient()
8282
{
8383
std::lock_guard<std::mutex> lock(mutex_);
8484
conn = std::dynamic_pointer_cast<TcpConnectionImpl>(connection_);
85-
}
86-
if (conn)
87-
{
88-
assert(loop_ == conn->getLoop());
89-
// TODO: not 100% safe, if we are in different thread
90-
auto loop = loop_;
91-
loop_->runInLoop([conn, loop]() {
92-
conn->setCloseCallback([loop](const TcpConnectionPtr &connPtr) {
93-
loop->queueInLoop([connPtr]() {
94-
static_cast<TcpConnectionImpl *>(connPtr.get())
95-
->connectDestroyed();
85+
if (conn)
86+
{
87+
assert(loop_ == conn->getLoop());
88+
// TODO: not 100% safe, if we are in different thread
89+
auto loop = loop_;
90+
loop_->runInLoop([conn, loop]() {
91+
conn->setCloseCallback([loop](const TcpConnectionPtr &connPtr) {
92+
loop->queueInLoop([connPtr]() {
93+
static_cast<TcpConnectionImpl *>(connPtr.get())
94+
->connectDestroyed();
95+
});
9696
});
9797
});
98-
});
99-
conn->forceClose();
100-
}
101-
else
102-
{
103-
connector_->stop();
98+
conn->forceClose();
99+
}
100+
else
101+
{
102+
connector_->stop();
103+
}
104104
}
105105
}
106106

@@ -166,7 +166,25 @@ void TcpClient::newConnection(int sockfd)
166166
conn->setConnectionCallback(connectionCallback_);
167167
conn->setRecvMsgCallback(messageCallback_);
168168
conn->setWriteCompleteCallback(writeCompleteCallback_);
169-
conn->setCloseCallback(std::bind(&TcpClient::removeConnection, this, _1));
169+
170+
std::weak_ptr<TcpClient> weakSelf(shared_from_this());
171+
auto closeCb = std::function<void(const TcpConnectionPtr &)>(
172+
[weakSelf](const TcpConnectionPtr &c) {
173+
if (auto self = weakSelf.lock())
174+
{
175+
self->removeConnection(c);
176+
}
177+
// Else the TcpClient instance has already been destroyed
178+
else
179+
{
180+
LOG_DEBUG << "TcpClient::removeConnection was skipped because "
181+
"TcpClient instanced already freed";
182+
c->getLoop()->queueInLoop(
183+
std::bind(&TcpConnectionImpl::connectDestroyed,
184+
std::dynamic_pointer_cast<TcpConnectionImpl>(c)));
185+
}
186+
});
187+
conn->setCloseCallback(std::move(closeCb));
170188
{
171189
std::lock_guard<std::mutex> lock(mutex_);
172190
connection_ = conn;

trantor/net/TcpClient.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ class SSLContext;
3434
* @brief This class represents a TCP client.
3535
*
3636
*/
37-
class TRANTOR_EXPORT TcpClient : NonCopyable
37+
class TRANTOR_EXPORT TcpClient : NonCopyable,
38+
public std::enable_shared_from_this<TcpClient>
3839
{
3940
public:
4041
/**

0 commit comments

Comments
 (0)