diff options
author | Tyler Seip <Tyler.Seip@mongodb.com> | 2021-11-29 16:50:34 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2021-11-29 17:48:31 +0000 |
commit | d2bca5f1c72212d05dd99a22b5ee1b283ecb65ed (patch) | |
tree | 29164d9586d3bd28f21320c1670a6c6b70a39376 /src/mongo/transport | |
parent | dcdf971889b00ef0b98815d8abff54add18cdcbe (diff) | |
download | mongo-d2bca5f1c72212d05dd99a22b5ee1b283ecb65ed.tar.gz |
SERVER-60603: Allow connection reset errors without assertion in ASIOSession::ensureSync()
Diffstat (limited to 'src/mongo/transport')
-rw-r--r-- | src/mongo/transport/session_asio.cpp | 8 | ||||
-rw-r--r-- | src/mongo/transport/transport_layer_asio_test.cpp | 33 |
2 files changed, 35 insertions, 6 deletions
diff --git a/src/mongo/transport/session_asio.cpp b/src/mongo/transport/session_asio.cpp index 3acecb954cf..3c957556f15 100644 --- a/src/mongo/transport/session_asio.cpp +++ b/src/mongo/transport/session_asio.cpp @@ -343,18 +343,14 @@ void TransportLayerASIO::ASIOSession::ensureSync() { "session send timeout", logv2::LogSeverity::Info(), ec); - if (auto status = errorCodeToStatus(ec); !status.isOK()) { - tasserted(5342000, status.reason()); - } + uassertStatusOK(errorCodeToStatus(ec)); setSocketOption(getSocket(), ASIOSocketTimeoutOption<SO_RCVTIMEO>(timeout), "session receive timeout", logv2::LogSeverity::Info(), ec); - if (auto status = errorCodeToStatus(ec); !status.isOK()) { - tasserted(5342001, status.reason()); - } + uassertStatusOK(errorCodeToStatus(ec)); _socketTimeout = _configuredTimeout; } diff --git a/src/mongo/transport/transport_layer_asio_test.cpp b/src/mongo/transport/transport_layer_asio_test.cpp index 344393602b8..af9fbd30e9a 100644 --- a/src/mongo/transport/transport_layer_asio_test.cpp +++ b/src/mongo/transport/transport_layer_asio_test.cpp @@ -351,6 +351,39 @@ TEST(TransportLayerASIO, TCPResetAfterConnectionIsSilentlySwallowed) { ASSERT_EQ(sessionsCreated.load(), 0); } +TEST(TransportLayerASIO, ThrowOnNetworkErrorInEnsureSync) { + TestFixture tf; + Notification<SessionThread*> mockSessionCreated; + tf.sep().setOnStartSession([&](SessionThread& st) { mockSessionCreated.set(&st); }); + + ConnectionThread connectThread(tf.tla().listenerPort(), [&](ConnectionThread& conn) { + // Linger timeout = 0 causes a RST packet on close. + struct linger sl = {1, 0}; + if (setsockopt(conn.socket().rawFD(), + SOL_SOCKET, + SO_LINGER, + reinterpret_cast<SetsockoptPtr>(&sl), + sizeof(sl)) != 0) { + auto err = make_error_code(std::errc{errno}); + LOGV2_ERROR(6060300, "setsockopt", "error"_attr = err.message()); + } + }); + + auto& st = *mockSessionCreated.get(); + connectThread.close(); + + // We set the timeout to ensure that the setsockopt calls are actually made in ensureSync() + st.session().setTimeout(Milliseconds{500}); + + // On Mac, setsockopt will immediately throw a SocketException since the socket is closed. + // On Linux, we will throw HostUnreachable once we try to actually read the socket. + // We allow for either exception here. + using namespace unittest::match; + ASSERT_THAT( + st.session().sourceMessage().getStatus(), + StatusIs(AnyOf(Eq(ErrorCodes::HostUnreachable), Eq(ErrorCodes::SocketException)), Any())); +} + /* check that timeouts actually time out */ TEST(TransportLayerASIO, SourceSyncTimeoutTimesOut) { TestFixture tf; |