Skip to content

Commit b108bf0

Browse files
committed
Fix bad_weak_ptr when close a ClientConnection during construction
Fixes apache#348 Fixes apache#349 ### Motivation When `close` is called in `ClientConnection`'s constructor, `shared_from_this()` will be called, which results in a `std::bad_weak_ptr` error. This error does not happen before apache#317 because `shared_from_this()` could only be called when the `producers` or `consumers` field is not empty. ### Modifications Modify the 2nd parameter of `ClientConnection::close` to represent if the construction completes. If not, just set the state to `Disconnected` and complete the future to the result. Then `ConnectionPool::getConnectionAsync` will return a future that completes with the failed result. In addition, check `authentication_` even for non-TLS URLs. Otherwise, the null authentication will be used to construct `CommandConnect`. Add `testInvalidPlugin` and `testTlsConfigError` to verify the changes.
1 parent 8d32fd2 commit b108bf0

File tree

3 files changed

+31
-16
lines changed

3 files changed

+31
-16
lines changed

lib/ClientConnection.cc

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,11 @@ ClientConnection::ClientConnection(const std::string& logicalAddress, const std:
186186
clientVersion_(clientVersion),
187187
pool_(pool) {
188188
LOG_INFO(cnxString_ << "Create ClientConnection, timeout=" << clientConfiguration.getConnectionTimeout());
189+
if (!authentication_) {
190+
LOG_ERROR("Invalid authentication plugin");
191+
close(ResultAuthenticationError, false);
192+
return;
193+
}
189194
if (clientConfiguration.isUseTls()) {
190195
#if BOOST_VERSION >= 105400
191196
boost::asio::ssl::context ctx(boost::asio::ssl::context::tlsv12_client);
@@ -214,12 +219,6 @@ ClientConnection::ClientConnection(const std::string& logicalAddress, const std:
214219
}
215220
}
216221

217-
if (!authentication_) {
218-
LOG_ERROR("Invalid authentication plugin");
219-
close(ResultAuthenticationError, false);
220-
return;
221-
}
222-
223222
std::string tlsCertificates = clientConfiguration.getTlsCertificateFilePath();
224223
std::string tlsPrivateKey = clientConfiguration.getTlsPrivateKeyFilePath();
225224

@@ -1259,7 +1258,13 @@ void ClientConnection::handleConsumerStatsTimeout(const boost::system::error_cod
12591258
startConsumerStatsTimer(consumerStatsRequests);
12601259
}
12611260

1262-
void ClientConnection::close(Result result, bool detach) {
1261+
void ClientConnection::close(Result result, bool constructCompleted) {
1262+
if (!constructCompleted) {
1263+
state_ = Disconnected;
1264+
connectPromise_.setFailed(result);
1265+
return;
1266+
}
1267+
12631268
Lock lock(mutex_);
12641269
if (isClosed()) {
12651270
return;
@@ -1319,9 +1324,7 @@ void ClientConnection::close(Result result, bool detach) {
13191324
LOG_INFO(cnxString_ << "Connection disconnected (refCnt: " << refCount << ")");
13201325
}
13211326
// Remove the connection from the pool before completing any promise
1322-
if (detach) {
1323-
pool_.remove(logicalAddress_, this); // trigger the destructor
1324-
}
1327+
pool_.remove(logicalAddress_, this);
13251328

13261329
auto self = shared_from_this();
13271330
for (ProducersMap::iterator it = producers.begin(); it != producers.end(); ++it) {

lib/ClientConnection.h

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -146,13 +146,9 @@ class PULSAR_PUBLIC ClientConnection : public std::enable_shared_from_this<Clien
146146
* Close the connection.
147147
*
148148
* @param result all pending futures will complete with this result
149-
* @param detach remove it from the pool if it's true
150-
*
151-
* `detach` should only be false when:
152-
* 1. Before the connection is put into the pool, i.e. during the construction.
153-
* 2. When the connection pool is closed
149+
* @param constructCompleted whether the construction is completed
154150
*/
155-
void close(Result result = ResultConnectError, bool detach = true);
151+
void close(Result result = ResultConnectError, bool constructCompleted = true);
156152

157153
bool isClosed() const;
158154

tests/AuthPluginTest.cc

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -581,3 +581,19 @@ TEST(AuthPluginTest, testOauth2Failure) {
581581
ASSERT_EQ(client5.createProducer(topic, producer), ResultAuthenticationError);
582582
client5.close();
583583
}
584+
585+
TEST(AuthPluginTest, testInvalidPlugin) {
586+
Client client("pulsar://localhost:6650", ClientConfiguration{}.setAuth(AuthFactory::create("invalid")));
587+
Producer producer;
588+
ASSERT_EQ(ResultAuthenticationError, client.createProducer("my-topic", producer));
589+
client.close();
590+
}
591+
592+
TEST(AuthPluginTest, testTlsConfigError) {
593+
Client client(serviceUrlTls, ClientConfiguration{}
594+
.setAuth(AuthTls::create(clientPublicKeyPath, clientPrivateKeyPath))
595+
.setTlsTrustCertsFilePath("invalid"));
596+
Producer producer;
597+
ASSERT_EQ(ResultAuthenticationError, client.createProducer("my-topic", producer));
598+
client.close();
599+
}

0 commit comments

Comments
 (0)