From 0f6d0e8c5a1d05437710682243cce398de8ee177 Mon Sep 17 00:00:00 2001 From: Oleg Pudeyev <39304720+p-mongo@users.noreply.github.com> Date: Mon, 23 Aug 2021 11:43:51 -0400 Subject: [PATCH] RUBY-2771 Allow awaited hello to fail with EOF when client is shutting down (#2328) Co-authored-by: Oleg Pudeyev --- lib/mongo/server/push_monitor.rb | 6 ++++ spec/stress/push_monitor_close_spec.rb | 44 ++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 spec/stress/push_monitor_close_spec.rb diff --git a/lib/mongo/server/push_monitor.rb b/lib/mongo/server/push_monitor.rb index 9c384ebdd1..cbc3926e19 100644 --- a/lib/mongo/server/push_monitor.rb +++ b/lib/mongo/server/push_monitor.rb @@ -111,6 +111,12 @@ def do_work @topology_version = new_description.topology_version end rescue Mongo::Error => exc + stop_requested = @lock.synchronize { @stop_requested } + if stop_requested + # Ignore the exception, see RUBY-2771. + return + end + msg = "Error running awaited hello on #{server.address}" Utils.warn_bg_exception(msg, exc, logger: options[:logger], diff --git a/spec/stress/push_monitor_close_spec.rb b/spec/stress/push_monitor_close_spec.rb new file mode 100644 index 0000000000..c79e2fa289 --- /dev/null +++ b/spec/stress/push_monitor_close_spec.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true +# encoding: utf-8 + +require 'spec_helper' + +# This test repeatedly creates and closes clients across several threads. +# Its goal is to ensure that the push monitor connections specifically get +# closed without any errors or warnings being reported to applications. +# +# Although the test is specifically meant to test 4.4+ servers (that utilize +# the push monitor) in non-LB connections, run it everywhere for good measure. +describe 'Push monitor close test' do + require_stress + + let(:options) do + SpecConfig.instance.all_test_options + end + + before(:all) do + # load if necessary + ClusterConfig.instance.primary_address + ClientRegistry.instance.close_all_clients + end + + it 'does not warn/error on cleanup' do + Mongo::Logger.logger.should_not receive(:warn) + + threads = 10.times.map do + Thread.new do + 10.times do + client = new_local_client([ClusterConfig.instance.primary_address.seed], options) + if rand > 0.33 + client.command(ping: 1) + sleep(rand * 3) + end + client.close + STDOUT << '.' + end + end + end + threads.each(&:join) + puts + end +end