summaryrefslogtreecommitdiff
path: root/src/mongo/executor/connection_pool_test.cpp
diff options
context:
space:
mode:
authorBen Caimano <ben.caimano@10gen.com>2019-06-30 13:35:40 -0400
committerBen Caimano <ben.caimano@10gen.com>2019-07-01 18:55:43 -0400
commitb9198150102c2edd2c2d27f0db2a96eaef9b6e38 (patch)
treeb27f2e1dba6d6840aee32f30a626a419166782ce /src/mongo/executor/connection_pool_test.cpp
parent6dabe5871fcd280f654e475e7048385b54b1ea64 (diff)
downloadmongo-b9198150102c2edd2c2d27f0db2a96eaef9b6e38.tar.gz
SERVER-42026 Lock during ConnectionPool::SpecificPool::spawnConnections()
Diffstat (limited to 'src/mongo/executor/connection_pool_test.cpp')
-rw-r--r--src/mongo/executor/connection_pool_test.cpp30
1 files changed, 23 insertions, 7 deletions
diff --git a/src/mongo/executor/connection_pool_test.cpp b/src/mongo/executor/connection_pool_test.cpp
index 048e694af4f..31b27dc9238 100644
--- a/src/mongo/executor/connection_pool_test.cpp
+++ b/src/mongo/executor/connection_pool_test.cpp
@@ -64,12 +64,28 @@ protected:
}
auto makePool(ConnectionPool::Options options = {}) {
- _pool =
- std::make_shared<ConnectionPool>(std::make_shared<PoolImpl>(), "test pool", options);
+ _pool = std::make_shared<ConnectionPool>(
+ std::make_shared<PoolImpl>(_executor), "test pool", options);
return _pool;
}
+ /**
+ * Get from a pool with out-of-line execution and return the future for a connection
+ *
+ * Since the InlineOutOfLineExecutor starts running on the same thread once schedule is called,
+ * this function allows us to avoid deadlocks with get(), which is the only public function that
+ * calls schedule while holding a lock. In normal operation, the OutOfLineExecutor is actually
+ * out of line, and this contrivance isn't necessary.
+ */
+ template <typename... Args>
+ auto getFromPool(Args&&... args) {
+ return ExecutorFuture(_executor)
+ .then([ pool = _pool, args... ]() { return pool->get(args...); })
+ .semi();
+ }
+
private:
+ std::shared_ptr<OutOfLineExecutor> _executor = std::make_shared<InlineOutOfLineExecutor>();
std::shared_ptr<ConnectionPool> _pool;
};
@@ -1440,7 +1456,7 @@ TEST_F(ConnectionPoolTest, AsyncGet) {
size_t connId = 0;
// no connections in the pool, our future is not satisfied
- auto connFuture = pool->get(HostAndPort(), transport::kGlobalSSLMode, Seconds{1});
+ auto connFuture = getFromPool(HostAndPort(), transport::kGlobalSSLMode, Seconds{1});
ASSERT_FALSE(connFuture.isReady());
// Successfully get a new connection
@@ -1463,8 +1479,8 @@ TEST_F(ConnectionPoolTest, AsyncGet) {
size_t connId2 = 0;
size_t connId3 = 0;
- auto connFuture1 = pool->get(HostAndPort(), transport::kGlobalSSLMode, Seconds{1});
- auto connFuture2 = pool->get(HostAndPort(), transport::kGlobalSSLMode, Seconds{10});
+ auto connFuture1 = getFromPool(HostAndPort(), transport::kGlobalSSLMode, Seconds{1});
+ auto connFuture2 = getFromPool(HostAndPort(), transport::kGlobalSSLMode, Seconds{10});
// The first future should be immediately ready. The second should be in the queue.
ASSERT_TRUE(connFuture1.isReady());
@@ -1475,7 +1491,7 @@ TEST_F(ConnectionPoolTest, AsyncGet) {
auto conn1 = std::move(connFuture1).get();
// Grab our third future while our first one is being fulfilled
- connFuture3 = pool->get(HostAndPort(), transport::kGlobalSSLMode, Seconds{1});
+ connFuture3 = getFromPool(HostAndPort(), transport::kGlobalSSLMode, Seconds{1});
connId1 = getId(conn1);
doneWith(conn1);
@@ -1512,7 +1528,7 @@ TEST_F(ConnectionPoolTest, ReturnAfterShutdown) {
auto pool = makePool();
// Grab a connection and hold it to end of scope
- auto connFuture = pool->get(HostAndPort(), transport::kGlobalSSLMode, Seconds(1));
+ auto connFuture = getFromPool(HostAndPort(), transport::kGlobalSSLMode, Seconds(1));
ConnectionImpl::pushSetup(Status::OK());
auto conn = std::move(connFuture).get();
doneWith(conn);