From 7308d4b6162df4e03024e74590f1100308b70309 Mon Sep 17 00:00:00 2001 From: Ken Rockot Date: Tue, 13 Dec 2022 06:35:56 +0000 Subject: [PATCH] Mojo: Remove MessageQuotaChecker This is effectively dead code, enabled only by feature flags which must be manually enabled and which were added for investigations that are no longer being done. The feature flags are also removed. Fixed: 1399511 Change-Id: I3e6462c728c1ee39848670a2bff4f29be61f1865 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4093879 Reviewed-by: Oksana Zhuravlova Reviewed-by: Avi Drissman Commit-Queue: Ken Rockot Reviewed-by: Zhenyao Mo Cr-Commit-Position: refs/heads/main@{#1082320} --- content/common/child_process_host_impl.cc | 7 +- gpu/ipc/client/gpu_channel_host.cc | 7 +- ipc/ipc_channel_common.cc | 7 +- ipc/ipc_channel_factory.cc | 15 +- ipc/ipc_channel_factory.h | 8 - ipc/ipc_channel_mojo.cc | 24 +- ipc/ipc_channel_mojo.h | 6 +- ipc/ipc_channel_proxy.cc | 9 - ipc/ipc_channel_proxy.h | 4 - ipc/ipc_mojo_bootstrap.cc | 23 +- ipc/ipc_mojo_bootstrap.h | 4 +- ipc/ipc_mojo_bootstrap_unittest.cc | 19 +- ipc/ipc_test_base.cc | 4 +- mojo/public/cpp/bindings/BUILD.gn | 2 - mojo/public/cpp/bindings/connector.h | 10 - mojo/public/cpp/bindings/lib/connector.cc | 19 - .../cpp/bindings/lib/message_quota_checker.cc | 377 ------------------ .../cpp/bindings/lib/message_quota_checker.h | 170 -------- .../cpp/bindings/lib/multiplex_router.cc | 6 - mojo/public/cpp/bindings/tests/BUILD.gn | 1 - .../tests/message_quota_checker_unittest.cc | 356 ----------------- 21 files changed, 34 insertions(+), 1044 deletions(-) delete mode 100644 mojo/public/cpp/bindings/lib/message_quota_checker.cc delete mode 100644 mojo/public/cpp/bindings/lib/message_quota_checker.h delete mode 100644 mojo/public/cpp/bindings/tests/message_quota_checker_unittest.cc diff --git a/content/common/child_process_host_impl.cc b/content/common/child_process_host_impl.cc index 6b19fabb823cc4..b9875db0314bca 100644 --- a/content/common/child_process_host_impl.cc +++ b/content/common/child_process_host_impl.cc @@ -34,7 +34,6 @@ #include "ipc/ipc_channel_mojo.h" #include "ipc/ipc_logging.h" #include "ipc/message_filter.h" -#include "mojo/public/cpp/bindings/lib/message_quota_checker.h" #include "services/resource_coordinator/public/mojom/memory_instrumentation/constants.mojom.h" #include "services/service_manager/public/cpp/interface_provider.h" @@ -126,8 +125,7 @@ ChildProcessHostImpl::ChildProcessHostImpl(ChildProcessHostDelegate* delegate, kChildProcessReceiverAttachmentName), IPC::Channel::MODE_SERVER, this, base::SingleThreadTaskRunner::GetCurrentDefault(), - base::SingleThreadTaskRunner::GetCurrentDefault(), - mojo::internal::MessageQuotaChecker::MaybeCreate()); + base::SingleThreadTaskRunner::GetCurrentDefault()); } else if (ipc_mode_ == IpcMode::kNormal) { child_process_.Bind(mojo::PendingRemote( mojo_invitation_->AttachMessagePipe( @@ -223,8 +221,7 @@ void ChildProcessHostImpl::CreateChannelMojo() { channel_ = IPC::ChannelMojo::Create( std::move(bootstrap), IPC::Channel::MODE_SERVER, this, base::SingleThreadTaskRunner::GetCurrentDefault(), - base::SingleThreadTaskRunner::GetCurrentDefault(), - mojo::internal::MessageQuotaChecker::MaybeCreate()); + base::SingleThreadTaskRunner::GetCurrentDefault()); } DCHECK(channel_); diff --git a/gpu/ipc/client/gpu_channel_host.cc b/gpu/ipc/client/gpu_channel_host.cc index 11e23861d6a757..a364f0ea41f5f3 100644 --- a/gpu/ipc/client/gpu_channel_host.cc +++ b/gpu/ipc/client/gpu_channel_host.cc @@ -17,7 +17,6 @@ #include "gpu/ipc/common/command_buffer_id.h" #include "gpu/ipc/common/gpu_watchdog_timeout.h" #include "ipc/ipc_channel_mojo.h" -#include "mojo/public/cpp/bindings/lib/message_quota_checker.h" #include "mojo/public/cpp/bindings/sync_call_restrictions.h" #include "url/gurl.h" @@ -215,9 +214,9 @@ void GpuChannelHost::Listener::Initialize( mojo::PendingAssociatedReceiver receiver, scoped_refptr io_task_runner) { base::AutoLock lock(lock_); - channel_ = IPC::ChannelMojo::Create( - std::move(handle), IPC::Channel::MODE_CLIENT, this, io_task_runner, - io_task_runner, mojo::internal::MessageQuotaChecker::MaybeCreate()); + channel_ = + IPC::ChannelMojo::Create(std::move(handle), IPC::Channel::MODE_CLIENT, + this, io_task_runner, io_task_runner); DCHECK(channel_); bool result = channel_->Connect(); DCHECK(result); diff --git a/ipc/ipc_channel_common.cc b/ipc/ipc_channel_common.cc index f3597d3b8202d6..9eb94f4bcd4979 100644 --- a/ipc/ipc_channel_common.cc +++ b/ipc/ipc_channel_common.cc @@ -6,7 +6,6 @@ #include "build/build_config.h" #include "ipc/ipc_channel.h" #include "ipc/ipc_channel_mojo.h" -#include "mojo/public/cpp/bindings/lib/message_quota_checker.h" #include "mojo/public/cpp/system/message_pipe.h" namespace IPC { @@ -41,8 +40,7 @@ std::unique_ptr Channel::CreateClient( return ChannelMojo::Create( mojo::ScopedMessagePipeHandle(channel_handle.mojo_handle), Channel::MODE_CLIENT, listener, ipc_task_runner, - base::SingleThreadTaskRunner::GetCurrentDefault(), - mojo::internal::MessageQuotaChecker::MaybeCreate()); + base::SingleThreadTaskRunner::GetCurrentDefault()); #endif } @@ -58,8 +56,7 @@ std::unique_ptr Channel::CreateServer( return ChannelMojo::Create( mojo::ScopedMessagePipeHandle(channel_handle.mojo_handle), Channel::MODE_SERVER, listener, ipc_task_runner, - base::SingleThreadTaskRunner::GetCurrentDefault(), - mojo::internal::MessageQuotaChecker::MaybeCreate()); + base::SingleThreadTaskRunner::GetCurrentDefault()); #endif } diff --git a/ipc/ipc_channel_factory.cc b/ipc/ipc_channel_factory.cc index 7f683632e053de..a24bd676937332 100644 --- a/ipc/ipc_channel_factory.cc +++ b/ipc/ipc_channel_factory.cc @@ -8,7 +8,6 @@ #include "base/task/single_thread_task_runner.h" #include "build/build_config.h" #include "ipc/ipc_channel_mojo.h" -#include "mojo/public/cpp/bindings/lib/message_quota_checker.h" namespace IPC { @@ -20,10 +19,7 @@ class PlatformChannelFactory : public ChannelFactory { ChannelHandle handle, Channel::Mode mode, const scoped_refptr& ipc_task_runner) - : handle_(handle), - mode_(mode), - ipc_task_runner_(ipc_task_runner), - quota_checker_(mojo::internal::MessageQuotaChecker::MaybeCreate()) {} + : handle_(handle), mode_(mode), ipc_task_runner_(ipc_task_runner) {} PlatformChannelFactory(const PlatformChannelFactory&) = delete; PlatformChannelFactory& operator=(const PlatformChannelFactory&) = delete; @@ -35,8 +31,7 @@ class PlatformChannelFactory : public ChannelFactory { DCHECK(handle_.is_mojo_channel_handle()); return ChannelMojo::Create( mojo::ScopedMessagePipeHandle(handle_.mojo_handle), mode_, listener, - ipc_task_runner_, base::SingleThreadTaskRunner::GetCurrentDefault(), - quota_checker_); + ipc_task_runner_, base::SingleThreadTaskRunner::GetCurrentDefault()); #endif } @@ -44,16 +39,10 @@ class PlatformChannelFactory : public ChannelFactory { return ipc_task_runner_; } - scoped_refptr GetQuotaChecker() - override { - return quota_checker_; - } - private: ChannelHandle handle_; Channel::Mode mode_; scoped_refptr ipc_task_runner_; - scoped_refptr quota_checker_; }; } // namespace diff --git a/ipc/ipc_channel_factory.h b/ipc/ipc_channel_factory.h index 5da6131956716d..0ed4606b81380e 100644 --- a/ipc/ipc_channel_factory.h +++ b/ipc/ipc_channel_factory.h @@ -14,12 +14,6 @@ #include "base/task/single_thread_task_runner.h" #include "ipc/ipc_channel.h" -namespace mojo { -namespace internal { -class MessageQuotaChecker; -} // namespace internal -} // namespace mojo - namespace IPC { // Encapsulates how a Channel is created. A ChannelFactory can be @@ -37,8 +31,6 @@ class COMPONENT_EXPORT(IPC) ChannelFactory { virtual ~ChannelFactory() { } virtual std::unique_ptr BuildChannel(Listener* listener) = 0; virtual scoped_refptr GetIPCTaskRunner() = 0; - virtual scoped_refptr - GetQuotaChecker() = 0; }; } // namespace IPC diff --git a/ipc/ipc_channel_mojo.cc b/ipc/ipc_channel_mojo.cc index d6c78468aa5937..974b96fcf33954 100644 --- a/ipc/ipc_channel_mojo.cc +++ b/ipc/ipc_channel_mojo.cc @@ -30,7 +30,6 @@ #include "mojo/public/cpp/bindings/associated_receiver.h" #include "mojo/public/cpp/bindings/associated_remote.h" #include "mojo/public/cpp/bindings/generic_pending_associated_receiver.h" -#include "mojo/public/cpp/bindings/lib/message_quota_checker.h" #include "mojo/public/cpp/bindings/pending_associated_receiver.h" #include "mojo/public/cpp/bindings/thread_safe_proxy.h" #include "mojo/public/cpp/system/platform_handle.h" @@ -49,33 +48,25 @@ class MojoChannelFactory : public ChannelFactory { : handle_(std::move(handle)), mode_(mode), ipc_task_runner_(ipc_task_runner), - proxy_task_runner_(proxy_task_runner), - quota_checker_(mojo::internal::MessageQuotaChecker::MaybeCreate()) {} + proxy_task_runner_(proxy_task_runner) {} MojoChannelFactory(const MojoChannelFactory&) = delete; MojoChannelFactory& operator=(const MojoChannelFactory&) = delete; std::unique_ptr BuildChannel(Listener* listener) override { return ChannelMojo::Create(std::move(handle_), mode_, listener, - ipc_task_runner_, proxy_task_runner_, - quota_checker_); + ipc_task_runner_, proxy_task_runner_); } scoped_refptr GetIPCTaskRunner() override { return ipc_task_runner_; } - scoped_refptr GetQuotaChecker() - override { - return quota_checker_; - } - private: mojo::ScopedMessagePipeHandle handle_; const Channel::Mode mode_; scoped_refptr ipc_task_runner_; scoped_refptr proxy_task_runner_; - scoped_refptr quota_checker_; }; class ThreadSafeChannelProxy : public mojo::ThreadSafeProxy { @@ -135,11 +126,9 @@ std::unique_ptr ChannelMojo::Create( Mode mode, Listener* listener, const scoped_refptr& ipc_task_runner, - const scoped_refptr& proxy_task_runner, - const scoped_refptr& quota_checker) { + const scoped_refptr& proxy_task_runner) { return base::WrapUnique(new ChannelMojo(std::move(handle), mode, listener, - ipc_task_runner, proxy_task_runner, - quota_checker)); + ipc_task_runner, proxy_task_runner)); } // static @@ -167,12 +156,11 @@ ChannelMojo::ChannelMojo( Mode mode, Listener* listener, const scoped_refptr& ipc_task_runner, - const scoped_refptr& proxy_task_runner, - const scoped_refptr& quota_checker) + const scoped_refptr& proxy_task_runner) : task_runner_(ipc_task_runner), pipe_(handle.get()), listener_(listener) { weak_ptr_ = weak_factory_.GetWeakPtr(); bootstrap_ = MojoBootstrap::Create(std::move(handle), mode, ipc_task_runner, - proxy_task_runner, quota_checker); + proxy_task_runner); } void ChannelMojo::ForwardMessage(mojo::Message message) { diff --git a/ipc/ipc_channel_mojo.h b/ipc/ipc_channel_mojo.h index 66f2e5e5923393..4eb44e014b746b 100644 --- a/ipc/ipc_channel_mojo.h +++ b/ipc/ipc_channel_mojo.h @@ -49,8 +49,7 @@ class COMPONENT_EXPORT(IPC) ChannelMojo Mode mode, Listener* listener, const scoped_refptr& ipc_task_runner, - const scoped_refptr& proxy_task_runner, - const scoped_refptr& quota_checker); + const scoped_refptr& proxy_task_runner); // Create a factory object for ChannelMojo. // The factory is used to create Mojo-based ChannelProxy family. @@ -102,8 +101,7 @@ class COMPONENT_EXPORT(IPC) ChannelMojo Mode mode, Listener* listener, const scoped_refptr& ipc_task_runner, - const scoped_refptr& proxy_task_runner, - const scoped_refptr& quota_checker); + const scoped_refptr& proxy_task_runner); void ForwardMessage(mojo::Message message); diff --git a/ipc/ipc_channel_proxy.cc b/ipc/ipc_channel_proxy.cc index fe3dd502cdc4b0..6073ff6b917e5e 100644 --- a/ipc/ipc_channel_proxy.cc +++ b/ipc/ipc_channel_proxy.cc @@ -224,9 +224,6 @@ void ChannelProxy::Context::Clear() { // Called on the IPC::Channel thread void ChannelProxy::Context::OnSendMessage(std::unique_ptr message) { - if (quota_checker_) - quota_checker_->AfterMessagesDequeued(1); - if (!channel_) { OnChannelClosed(); return; @@ -422,9 +419,6 @@ void ChannelProxy::Context::AddGenericAssociatedInterfaceForIOThread( } void ChannelProxy::Context::Send(Message* message) { - if (quota_checker_) - quota_checker_->BeforeMessagesEnqueued(1); - ipc_task_runner()->PostTask( FROM_HERE, base::BindOnce(&ChannelProxy::Context::OnSendMessage, this, base::WrapUnique(message))); @@ -503,9 +497,6 @@ void ChannelProxy::Init(std::unique_ptr factory, DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(!did_init_); - DCHECK(!context_->quota_checker_); - context_->quota_checker_ = factory->GetQuotaChecker(); - if (create_pipe_now) { // Create the channel immediately. This effectively sets up the // low-level pipe so that the client can connect. Without creating diff --git a/ipc/ipc_channel_proxy.h b/ipc/ipc_channel_proxy.h index 58a6937b0de301..c9be29e9519656 100644 --- a/ipc/ipc_channel_proxy.h +++ b/ipc/ipc_channel_proxy.h @@ -27,7 +27,6 @@ #include "ipc/ipc_sender.h" #include "mojo/public/cpp/bindings/associated_remote.h" #include "mojo/public/cpp/bindings/generic_pending_associated_receiver.h" -#include "mojo/public/cpp/bindings/lib/message_quota_checker.h" #include "mojo/public/cpp/bindings/pending_associated_receiver.h" #include "mojo/public/cpp/bindings/pending_associated_remote.h" #include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" @@ -368,9 +367,6 @@ class COMPONENT_EXPORT(IPC) ChannelProxy : public Sender { std::unique_ptr channel_; bool channel_connected_called_; - // The quota checker associated with this channel, if any. - scoped_refptr quota_checker_; - // Lock for |channel_| value. This is only relevant in the context of // thread-safe send. base::Lock channel_lifetime_lock_; diff --git a/ipc/ipc_mojo_bootstrap.cc b/ipc/ipc_mojo_bootstrap.cc index d68f1a3c02fd53..6ecb81b6e6a02c 100644 --- a/ipc/ipc_mojo_bootstrap.cc +++ b/ipc/ipc_mojo_bootstrap.cc @@ -140,11 +140,9 @@ class ChannelAssociatedGroupController ChannelAssociatedGroupController( bool set_interface_id_namespace_bit, const scoped_refptr& ipc_task_runner, - const scoped_refptr& proxy_task_runner, - const scoped_refptr& quota_checker) + const scoped_refptr& proxy_task_runner) : task_runner_(ipc_task_runner), proxy_task_runner_(proxy_task_runner), - quota_checker_(quota_checker), set_interface_id_namespace_bit_(set_interface_id_namespace_bit), dispatcher_(this), control_message_handler_(this), @@ -202,8 +200,6 @@ class ChannelAssociatedGroupController base::AutoLock lock(outgoing_messages_lock_); std::swap(outgoing_messages, outgoing_messages_); } - if (quota_checker_ && outgoing_messages.size()) - quota_checker_->AfterMessagesDequeued(outgoing_messages.size()); for (auto& message : outgoing_messages) SendMessage(&message); @@ -220,8 +216,6 @@ class ChannelAssociatedGroupController base::BindOnce(&ChannelAssociatedGroupController::OnPipeError, base::Unretained(this))); connector_->set_enforce_errors_from_incoming_receiver(false); - if (quota_checker_) - connector_->SetMessageQuotaChecker(quota_checker_); // Don't let the Connector do any sort of queuing on our behalf. Individual // messages bound for the IPC::ChannelProxy thread (i.e. that vast majority @@ -272,9 +266,6 @@ class ChannelAssociatedGroupController connector_.reset(); base::AutoLock lock(outgoing_messages_lock_); - if (quota_checker_ && outgoing_messages_.size()) - quota_checker_->AfterMessagesDequeued(outgoing_messages_.size()); - outgoing_messages_.clear(); } @@ -821,8 +812,6 @@ class ChannelAssociatedGroupController if (!connector_ || paused_) { if (!shut_down_) { base::AutoLock lock(outgoing_messages_lock_); - if (quota_checker_) - quota_checker_->BeforeMessagesEnqueued(1); outgoing_messages_.emplace_back(std::move(*message)); } return true; @@ -1163,7 +1152,6 @@ class ChannelAssociatedGroupController scoped_refptr task_runner_; const scoped_refptr proxy_task_runner_; - const scoped_refptr quota_checker_; const bool set_interface_id_namespace_bit_; bool paused_ = false; std::unique_ptr connector_; @@ -1292,12 +1280,11 @@ std::unique_ptr MojoBootstrap::Create( mojo::ScopedMessagePipeHandle handle, Channel::Mode mode, const scoped_refptr& ipc_task_runner, - const scoped_refptr& proxy_task_runner, - const scoped_refptr& quota_checker) { + const scoped_refptr& proxy_task_runner) { return std::make_unique( - std::move(handle), base::MakeRefCounted( - mode == Channel::MODE_SERVER, ipc_task_runner, - proxy_task_runner, quota_checker)); + std::move(handle), + base::MakeRefCounted( + mode == Channel::MODE_SERVER, ipc_task_runner, proxy_task_runner)); } } // namespace IPC diff --git a/ipc/ipc_mojo_bootstrap.h b/ipc/ipc_mojo_bootstrap.h index 43156e541d5ba4..b432e448303637 100644 --- a/ipc/ipc_mojo_bootstrap.h +++ b/ipc/ipc_mojo_bootstrap.h @@ -18,7 +18,6 @@ #include "ipc/ipc_listener.h" #include "mojo/public/cpp/bindings/associated_group.h" #include "mojo/public/cpp/bindings/associated_remote.h" -#include "mojo/public/cpp/bindings/lib/message_quota_checker.h" #include "mojo/public/cpp/bindings/pending_associated_receiver.h" #include "mojo/public/cpp/system/message_pipe.h" @@ -102,8 +101,7 @@ class COMPONENT_EXPORT(IPC) MojoBootstrap { mojo::ScopedMessagePipeHandle handle, Channel::Mode mode, const scoped_refptr& ipc_task_runner, - const scoped_refptr& proxy_task_runner, - const scoped_refptr& quota_checker); + const scoped_refptr& proxy_task_runner); // Initialize the Channel pipe and interface endpoints. This performs all // setup except actually starting to read messages off the pipe. diff --git a/ipc/ipc_mojo_bootstrap_unittest.cc b/ipc/ipc_mojo_bootstrap_unittest.cc index 723dfc28ad9ba0..8771bcdd69041d 100644 --- a/ipc/ipc_mojo_bootstrap_unittest.cc +++ b/ipc/ipc_mojo_bootstrap_unittest.cc @@ -118,13 +118,12 @@ class IPCMojoBootstrapTest : public testing::Test { TEST_F(IPCMojoBootstrapTest, Connect) { base::test::SingleThreadTaskEnvironment task_environment; - Connection connection( - IPC::MojoBootstrap::Create( - helper_.StartChild("IPCMojoBootstrapTestClient"), - IPC::Channel::MODE_SERVER, - base::SingleThreadTaskRunner::GetCurrentDefault(), - base::SingleThreadTaskRunner::GetCurrentDefault(), nullptr), - kTestServerPid); + Connection connection(IPC::MojoBootstrap::Create( + helper_.StartChild("IPCMojoBootstrapTestClient"), + IPC::Channel::MODE_SERVER, + base::SingleThreadTaskRunner::GetCurrentDefault(), + base::SingleThreadTaskRunner::GetCurrentDefault()), + kTestServerPid); mojo::PendingAssociatedReceiver receiver; connection.TakeReceiver(&receiver); @@ -149,7 +148,7 @@ MULTIPROCESS_TEST_MAIN_WITH_SETUP( std::move(mojo::core::test::MultiprocessTestHelper::primordial_pipe), IPC::Channel::MODE_CLIENT, base::SingleThreadTaskRunner::GetCurrentDefault(), - base::SingleThreadTaskRunner::GetCurrentDefault(), nullptr), + base::SingleThreadTaskRunner::GetCurrentDefault()), kTestClientPid); mojo::PendingAssociatedReceiver receiver; @@ -171,7 +170,7 @@ TEST_F(IPCMojoBootstrapTest, ReceiveEmptyMessage) { helper_.StartChild("IPCMojoBootstrapTestEmptyMessage"), IPC::Channel::MODE_SERVER, base::SingleThreadTaskRunner::GetCurrentDefault(), - base::SingleThreadTaskRunner::GetCurrentDefault(), nullptr), + base::SingleThreadTaskRunner::GetCurrentDefault()), kTestServerPid); mojo::PendingAssociatedReceiver receiver; @@ -199,7 +198,7 @@ MULTIPROCESS_TEST_MAIN_WITH_SETUP( std::move(mojo::core::test::MultiprocessTestHelper::primordial_pipe), IPC::Channel::MODE_CLIENT, base::SingleThreadTaskRunner::GetCurrentDefault(), - base::SingleThreadTaskRunner::GetCurrentDefault(), nullptr), + base::SingleThreadTaskRunner::GetCurrentDefault()), kTestClientPid); mojo::PendingAssociatedReceiver receiver; diff --git a/ipc/ipc_test_base.cc b/ipc/ipc_test_base.cc index 865d6cd54f1249..49dc73842de2ec 100644 --- a/ipc/ipc_test_base.cc +++ b/ipc/ipc_test_base.cc @@ -33,7 +33,7 @@ void IPCChannelMojoTestBase::CreateChannel(IPC::Listener* listener) { channel_ = IPC::ChannelMojo::Create( TakeHandle(), IPC::Channel::MODE_SERVER, listener, base::SingleThreadTaskRunner::GetCurrentDefault(), - base::SingleThreadTaskRunner::GetCurrentDefault(), nullptr); + base::SingleThreadTaskRunner::GetCurrentDefault()); } bool IPCChannelMojoTestBase::ConnectChannel() { @@ -60,7 +60,7 @@ void IpcChannelMojoTestClient::Connect(IPC::Listener* listener) { channel_ = IPC::ChannelMojo::Create( std::move(handle_), IPC::Channel::MODE_CLIENT, listener, base::SingleThreadTaskRunner::GetCurrentDefault(), - base::SingleThreadTaskRunner::GetCurrentDefault(), nullptr); + base::SingleThreadTaskRunner::GetCurrentDefault()); CHECK(channel_->Connect()); } diff --git a/mojo/public/cpp/bindings/BUILD.gn b/mojo/public/cpp/bindings/BUILD.gn index c080f1afc48576..aa7a4e45580b4a 100644 --- a/mojo/public/cpp/bindings/BUILD.gn +++ b/mojo/public/cpp/bindings/BUILD.gn @@ -169,8 +169,6 @@ component("bindings") { "lib/interface_ptr_state.h", "lib/interface_serialization.h", "lib/message_dispatcher.cc", - "lib/message_quota_checker.cc", - "lib/message_quota_checker.h", "lib/multiplex_router.cc", "lib/multiplex_router.h", "lib/native_enum_data.h", diff --git a/mojo/public/cpp/bindings/connector.h b/mojo/public/cpp/bindings/connector.h index 4bc9f721046a13..a35ba18dc3f6f8 100644 --- a/mojo/public/cpp/bindings/connector.h +++ b/mojo/public/cpp/bindings/connector.h @@ -30,9 +30,6 @@ class Lock; } namespace mojo { -namespace internal { -class MessageQuotaChecker; -} class SyncHandleWatcher; @@ -224,10 +221,6 @@ class COMPONENT_EXPORT(MOJO_CPP_BINDINGS) Connector : public MessageReceiver { base::SequencedTaskRunner* task_runner() const { return task_runner_.get(); } - // Sets the quota checker. - void SetMessageQuotaChecker( - scoped_refptr checker); - // Allows testing environments to override the default serialization behavior // of newly constructed Connector instances. Must be called before any // Connector instances are constructed. @@ -334,9 +327,6 @@ class COMPONENT_EXPORT(MOJO_CPP_BINDINGS) Connector : public MessageReceiver { SEQUENCE_CHECKER(sequence_checker_); - // The quota checker associate with this connector, if any. - scoped_refptr quota_checker_; - // Indicates whether the Connector is configured to actively read from its // message pipe. As long as this is true, the Connector is only safe to // destroy in sequence with `task_runner_` tasks. diff --git a/mojo/public/cpp/bindings/lib/connector.cc b/mojo/public/cpp/bindings/lib/connector.cc index b69c53d5f6fc18..5835675ff84592 100644 --- a/mojo/public/cpp/bindings/lib/connector.cc +++ b/mojo/public/cpp/bindings/lib/connector.cc @@ -28,7 +28,6 @@ #include "mojo/public/c/system/quota.h" #include "mojo/public/cpp/bindings/features.h" #include "mojo/public/cpp/bindings/lib/may_auto_lock.h" -#include "mojo/public/cpp/bindings/lib/message_quota_checker.h" #include "mojo/public/cpp/bindings/mojo_buildflags.h" #include "mojo/public/cpp/bindings/sync_handle_watcher.h" #include "mojo/public/cpp/bindings/tracing_helpers.h" @@ -182,13 +181,6 @@ Connector::Connector(ScopedMessagePipeHandle message_pipe, } Connector::~Connector() { - if (quota_checker_) { - // Clear the message pipe handle in the checker. - quota_checker_->SetMessagePipe(MessagePipeHandle()); - UMA_HISTOGRAM_COUNTS_1M("Mojo.Connector.MaxUnreadMessageQuotaUsed", - quota_checker_->GetMaxQuotaUsage()); - } - if (is_receiving_) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); CancelWait(); @@ -351,9 +343,6 @@ bool Connector::Accept(Message* message) { } } - if (quota_checker_) - quota_checker_->BeforeWrite(); - MojoResult rv = WriteMessageNew(message_pipe_.get(), message->TakeMojoMessage(), MOJO_WRITE_MESSAGE_FLAG_NONE); @@ -398,14 +387,6 @@ void Connector::AllowWokenUpBySyncWatchOnSameThread() { sync_watcher_->AllowWokenUpBySyncWatchOnSameThread(); } -void Connector::SetMessageQuotaChecker( - scoped_refptr checker) { - DCHECK(checker && !quota_checker_); - - quota_checker_ = std::move(checker); - quota_checker_->SetMessagePipe(message_pipe_.get()); -} - // static void Connector::OverrideDefaultSerializationBehaviorForTesting( OutgoingSerializationMode outgoing_mode, diff --git a/mojo/public/cpp/bindings/lib/message_quota_checker.cc b/mojo/public/cpp/bindings/lib/message_quota_checker.cc deleted file mode 100644 index 8921b41146873e..00000000000000 --- a/mojo/public/cpp/bindings/lib/message_quota_checker.cc +++ /dev/null @@ -1,377 +0,0 @@ -// Copyright 2019 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/lib/message_quota_checker.h" - -#include - -#include "base/check_op.h" -#include "base/debug/activity_tracker.h" -#include "base/debug/alias.h" -#include "base/debug/dump_without_crashing.h" -#include "base/memory/scoped_refptr.h" -#include "base/metrics/field_trial_params.h" -#include "base/rand_util.h" -#include "base/synchronization/lock.h" -#include "base/types/pass_key.h" -#include "mojo/public/c/system/quota.h" -#include "mojo/public/cpp/bindings/features.h" -#include "mojo/public/cpp/bindings/mojo_buildflags.h" - -namespace mojo { -namespace internal { -namespace { - -const base::FeatureParam kMojoRecordUnreadMessageCountSampleRate = { - &features::kMojoRecordUnreadMessageCount, "SampleRate", - 100 // Sample 1% of Connectors by default. */ -}; - -const base::FeatureParam kMojoRecordUnreadMessageCountQuotaValue = { - &features::kMojoRecordUnreadMessageCount, "QuotaValue", - 100 // Use a 100 message quote by default. -}; - -const base::FeatureParam kMojoRecordUnreadMessageCountCrashThreshold = { - &features::kMojoRecordUnreadMessageCount, "CrashThreshold", - 0 // Set to zero to disable crash dumps by default. -}; - -NOINLINE void MaybeDumpWithoutCrashing( - size_t total_quota_used, - absl::optional message_pipe_quota_used, - int64_t seconds_since_construction, - double average_write_rate, - uint64_t messages_enqueued, - uint64_t messages_dequeued, - uint64_t messages_written) { - static bool have_crashed = false; - if (have_crashed) - return; - - // Only crash once per process/per run. Note that this is slightly racy - // against concurrent quota overruns on multiple threads, but that's fine. - have_crashed = true; - - size_t local_quota_used = total_quota_used; - bool had_message_pipe = false; - if (message_pipe_quota_used.has_value()) { - had_message_pipe = true; - local_quota_used -= message_pipe_quota_used.value(); - } - - // Normalize the write rate to writes/second. - double average_write_rate_per_second = - average_write_rate / - MessageQuotaChecker::DecayingRateAverage::kSamplingInterval.InSecondsF(); - base::debug::Alias(&total_quota_used); - base::debug::Alias(&local_quota_used); - base::debug::Alias(&had_message_pipe); - base::debug::Alias(&seconds_since_construction); - base::debug::Alias(&average_write_rate_per_second); - - // Note that these values are acquired non-atomically with respect to the - // variables above, and so may have increased since the quota overflow - // occurred. They will still give a good indication of the traffic and the - // traffic mix on this MessageQuotaChecker. - base::debug::Alias(&messages_enqueued); - base::debug::Alias(&messages_dequeued); - base::debug::Alias(&messages_written); - - // Also record the data for extended crash reporting. - base::debug::ScopedActivity scoped_activity; - auto& user_data = scoped_activity.user_data(); - user_data.SetUint("total_quota_used", total_quota_used); - user_data.SetUint("local_quota_used", local_quota_used); - user_data.SetBool("had_message_pipe", had_message_pipe); - user_data.SetUint("seconds_since_construction", seconds_since_construction); - user_data.SetUint("average_write_rate_per_second", - static_cast(average_write_rate_per_second)); - user_data.SetUint("messages_enqueued", messages_enqueued); - user_data.SetUint("messages_dequeued", messages_dequeued); - user_data.SetUint("messages_enqueued", messages_enqueued); - user_data.SetUint("messages_written", messages_written); - - // This is happening because the user of the interface implicated on the crash - // stack has queued up an unreasonable number of messages, namely - // |total_quota_used|. - base::debug::DumpWithoutCrashing(); -} - -int64_t ToSamplingInterval(base::TimeTicks when) { - return (when - base::TimeTicks::UnixEpoch()) - .IntDiv(MessageQuotaChecker::DecayingRateAverage::kSamplingInterval); -} - -base::TimeTicks FromSamplingInterval(int64_t sampling_interval) { - return MessageQuotaChecker::DecayingRateAverage::kSamplingInterval * - sampling_interval + - base::TimeTicks::UnixEpoch(); -} - -} // namespace - -constexpr base::TimeDelta - MessageQuotaChecker::DecayingRateAverage::kSamplingInterval; -constexpr double MessageQuotaChecker::DecayingRateAverage::kSampleWeight; - -// static -scoped_refptr MessageQuotaChecker::MaybeCreate() { - static const Configuration config = GetConfiguration(); - return MaybeCreateImpl(config); -} - -void MessageQuotaChecker::BeforeWrite() { - ++messages_written_; - QuotaCheckImpl(0u); -} - -void MessageQuotaChecker::BeforeMessagesEnqueued(size_t num) { - DCHECK_NE(num, 0u); - messages_enqueued_ += num; - QuotaCheckImpl(num); -} - -void MessageQuotaChecker::AfterMessagesDequeued(size_t num) { - base::AutoLock hold(lock_); - DCHECK_LE(num, consumed_quota_); - DCHECK_NE(num, 0u); - messages_dequeued_ += num; - consumed_quota_ -= num; -} - -size_t MessageQuotaChecker::GetMaxQuotaUsage() { - base::AutoLock hold(lock_); - return max_consumed_quota_; -} - -void MessageQuotaChecker::SetMessagePipe(MessagePipeHandle message_pipe) { - base::AutoLock hold(lock_); - message_pipe_ = message_pipe; - if (!message_pipe_) - return; - - MojoResult rv = - MojoSetQuota(message_pipe.value(), MOJO_QUOTA_TYPE_UNREAD_MESSAGE_COUNT, - config_->unread_message_count_quota, nullptr); - DCHECK_EQ(MOJO_RESULT_OK, rv); -} - -size_t MessageQuotaChecker::GetCurrentQuotaStatusForTesting() { - base::AutoLock hold(lock_); - size_t quota_used = consumed_quota_; - absl::optional message_pipe_quota_used = GetCurrentMessagePipeQuota(); - if (message_pipe_quota_used.has_value()) - quota_used += message_pipe_quota_used.value(); - - return quota_used; -} - -// static -MessageQuotaChecker::Configuration -MessageQuotaChecker::GetConfigurationForTesting() { - return GetConfiguration(); -} - -// static -scoped_refptr MessageQuotaChecker::MaybeCreateForTesting( - const Configuration& config) { - return MaybeCreateImpl(config); -} - -MessageQuotaChecker::MessageQuotaChecker(const Configuration* config, - base::PassKey) - : config_(config), creation_time_(base::TimeTicks::Now()) {} -MessageQuotaChecker::~MessageQuotaChecker() = default; - -// static -MessageQuotaChecker::Configuration MessageQuotaChecker::GetConfiguration() { - // Const since this may be called from any thread. Initialization is - // thread-safe. This is a workaround since some consumers of Mojo (e.g. many - // browser tests) use base::FeatureList incorrectly and thus cause data races - // when features are queried from arbitrary threads. - static const bool is_enabled = - base::FeatureList::IsEnabled(features::kMojoRecordUnreadMessageCount); - - Configuration ret; - ret.is_enabled = is_enabled; - ret.sample_rate = kMojoRecordUnreadMessageCountSampleRate.Get(); - - // Lower-bound the quota value to 100, which implies roughly 2% message - // overhead for sampled pipes. - constexpr int kMinQuotaValue = 100; - ret.unread_message_count_quota = - std::max(kMinQuotaValue, kMojoRecordUnreadMessageCountQuotaValue.Get()); - ret.crash_threshold = kMojoRecordUnreadMessageCountCrashThreshold.Get(); - ret.maybe_crash_function = &MaybeDumpWithoutCrashing; - return ret; -} - -// static -scoped_refptr MessageQuotaChecker::MaybeCreateImpl( - const Configuration& config) { - if (!config.is_enabled) - return nullptr; - - if (base::RandInt(0, config.sample_rate - 1) != 0) - return nullptr; - - return base::MakeRefCounted( - &config, base::PassKey()); -} - -absl::optional MessageQuotaChecker::GetCurrentMessagePipeQuota() { - lock_.AssertAcquired(); - - if (!message_pipe_) - return absl::nullopt; - - uint64_t limit = 0; - uint64_t usage = 0; - MojoResult rv = MojoQueryQuota(message_pipe_.value(), - MOJO_QUOTA_TYPE_UNREAD_MESSAGE_COUNT, nullptr, - &limit, &usage); - DCHECK_NE(MOJO_QUOTA_LIMIT_NONE, limit); - return rv == MOJO_RESULT_OK ? usage : 0u; -} - -void MessageQuotaChecker::QuotaCheckImpl(size_t num_enqueued) { - bool new_max = false; - - // By the time a crash is reported, another thread might have consumed some of - // the locally queued messages, and/or the message pipe might have been unset. - // To make the crash reports as useful as possible, grab the state of the - // local and the message pipe queues into individual variables, then pass them - // into the crashing function. - size_t total_quota_used = 0u; - base::TimeTicks now; - double average_write_rate = 0.0; - absl::optional message_pipe_quota_used; - { - base::AutoLock hold(lock_); - - message_pipe_quota_used = GetCurrentMessagePipeQuota(); - now = base::TimeTicks::Now(); - if (num_enqueued) { - consumed_quota_ += num_enqueued; - } else { - // BeforeWrite passes num_enqueued zero, as the message won't be locally - // enqueued. The assumption is that there's already a message pipe in - // play, and that the caller is keeping it alive somehow. - DCHECK(message_pipe_); - DCHECK(message_pipe_quota_used.has_value()); - - // Accrue this write event to the write rate average. - write_rate_average_.AccrueEvent(now); - - // Account for the message about to be written to the message pipe in the - // the full tally. - ++message_pipe_quota_used.value(); - } - - total_quota_used += consumed_quota_; - if (message_pipe_quota_used.has_value()) - total_quota_used += message_pipe_quota_used.value(); - - if (total_quota_used > max_consumed_quota_) { - max_consumed_quota_ = total_quota_used; - new_max = true; - // Retrieve the average rate, in the case that a crash is imminent. - average_write_rate = write_rate_average_.GetDecayedRateAverage(now); - } - } - - if (new_max && config_->crash_threshold != 0 && - total_quota_used >= config_->crash_threshold) { - DCHECK(!now.is_null()); - int64_t seconds_since_construction = (now - creation_time_).InSeconds(); - config_->maybe_crash_function( - total_quota_used, message_pipe_quota_used, seconds_since_construction, - average_write_rate, messages_enqueued_.load(), - messages_dequeued_.load(), messages_written_.load()); - } -} - -MessageQuotaChecker::DecayingRateAverage::DecayingRateAverage() { - events_sampling_interval_ = ToSamplingInterval(base::TimeTicks::Now()); -} - -void MessageQuotaChecker::DecayingRateAverage::AccrueEvent( - base::TimeTicks when) { - const int64_t sampling_interval = ToSamplingInterval(when); - DCHECK_GE(sampling_interval, events_sampling_interval_); - if (sampling_interval == events_sampling_interval_) { - // The time is still in the sampling interval, just add the event. - ++events_; - return; - } - DCHECK_GT(sampling_interval, events_sampling_interval_); - - // Add the new sample and decay it to the previous event sampling interval. - decayed_average_ = events_ * kSampleWeight + decayed_average_ * kDecayFactor; - - // Decay the average to the current sampling interval - 1. - const int64_t decayed_average_age = - sampling_interval - events_sampling_interval_ - 1; - if (decayed_average_age) - decayed_average_ *= pow(kDecayFactor, decayed_average_age); - - // Start a new event sampling interval. - events_ = 1; - events_sampling_interval_ = sampling_interval; -} - -double MessageQuotaChecker::DecayingRateAverage::GetDecayedRateAverage( - base::TimeTicks when) const { - // Three cases: - // - |when| is exactly at the start of a sampling interval. - // - |when| is within the current sampling interval. - // - |when| is beyond the end of the current sampling interval. - const int64_t sampling_interval = ToSamplingInterval(when); - double age_in_sampling_intervals = - (when - FromSamplingInterval(events_sampling_interval_)) / - kSamplingInterval; - DCHECK_LE(0.0, age_in_sampling_intervals); - if (when == FromSamplingInterval(events_sampling_interval_)) { - DCHECK_EQ(0.0, age_in_sampling_intervals); - // It is possible that an event has been accrued to the very start of a - // sampling interval. Technically this converges like so: - // - // lim when t -> 0 = - events_ * log(kDecayFactor) / kSamplingInterval - // - // For simplicity's sake, this is treated as synonymous with the decayed - // average at the end of the previous sampling interval here. - return decayed_average_; - } else if (sampling_interval == events_sampling_interval_) { - DCHECK_GT(1.0, age_in_sampling_intervals); - - // Use a decay factor that's exponential in the age |when|, relative to - // the sampling interval. This yields a stabler estimate than straight up - // extrapolating the rate to the end of the sampling interval, as that - // method is very sensitive to noise in sample timing near zero age. - double decay_factor = pow(kDecayFactor, age_in_sampling_intervals); - // Scale up the events collected so far to the rate. - double event_rate = events_ / age_in_sampling_intervals; - - return event_rate * (1.0 - decay_factor) + decayed_average_ * decay_factor; - } else { - DCHECK_LE(1.0, age_in_sampling_intervals); - // Compute the decayed average to the start of - // events_sampling_interval_ + 1. - double average = events_ * kSampleWeight + decayed_average_ * kDecayFactor; - - // And age it to |when|. - return average * pow(kDecayFactor, age_in_sampling_intervals - 1.0); - } -} - -// static -base::TimeTicks -MessageQuotaChecker::DecayingRateAverage::GetNextSamplingIntervalForTesting( - base::TimeTicks when) { - return FromSamplingInterval(ToSamplingInterval(when) + 1); -} - -} // namespace internal -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/message_quota_checker.h b/mojo/public/cpp/bindings/lib/message_quota_checker.h deleted file mode 100644 index 3e1752c824dc15..00000000000000 --- a/mojo/public/cpp/bindings/lib/message_quota_checker.h +++ /dev/null @@ -1,170 +0,0 @@ -// Copyright 2019 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_MESSAGE_QUOTA_CHECKER_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_MESSAGE_QUOTA_CHECKER_H_ - -#include -#include - -#include "base/component_export.h" -#include "base/memory/raw_ptr.h" -#include "base/memory/ref_counted.h" -#include "base/synchronization/lock.h" -#include "base/thread_annotations.h" -#include "base/time/time.h" -#include "base/types/pass_key.h" -#include "mojo/public/cpp/system/message_pipe.h" -#include "third_party/abseil-cpp/absl/types/optional.h" - -namespace mojo { -namespace internal { - -// This class keeps track of how many messages are in-flight for a message pipe, -// including messages that are posted or locally queued. -// -// Message pipe owners may have reason to implement their own mechanism for -// queuing outgoing messages before writing them to a pipe. This class helps -// with unread message quota monitoring in such cases, since Mojo's own -// quota monitoring on the pipe cannot account for such external queues. -// Callers are responsible for invoking |BeforeMessagesEnqueued()| and -// |AfterMessagesDequeued()| when making respective changes to their local -// outgoing queue. Additionally, |BeforeWrite()| should be called immediately -// before writing each message to the corresponding message pipe. -// -// Also note that messages posted to a different sequence with base::ThreadPool -// and the like, need to be treated as locally queued. Task queues can grow -// arbitrarily long, and it's ideal to perform unread quota checks before -// posting. -// -// Either |BeforeMessagesEnqueued()| or |BeforeWrite()| may cause the quota -// to be exceeded, thus invoking the |maybe_crash_function| set in this -// object's Configuration. -class COMPONENT_EXPORT(MOJO_CPP_BINDINGS) MessageQuotaChecker - : public base::RefCountedThreadSafe { - public: - // A helper class to maintain a decaying average for the rate of events per - // sampling interval over time. - class COMPONENT_EXPORT(MOJO_CPP_BINDINGS) DecayingRateAverage { - public: - DecayingRateAverage(); - - // Accrues one event at time |when|. Note that |when| must increase - // monotonically from one event to the next. - void AccrueEvent(base::TimeTicks when); - // Retrieves the current rate average, decayed to |when|. - double GetDecayedRateAverage(base::TimeTicks when) const; - - // The length of a sampling interval in seconds. - static constexpr base::TimeDelta kSamplingInterval = base::Seconds(5); - - // Returns the start of the sampling interval after the interval that - // |when| falls into. - static base::TimeTicks GetNextSamplingIntervalForTesting( - base::TimeTicks when); - - private: - // A new sample is weighed at this rate into the average, whereas the old - // average is weighed at kDecayFactor^age; Note that - // (kSampleWeight + kDecayFactor) == 1.0. - static constexpr double kSampleWeight = 0.5; - static constexpr double kDecayFactor = (1 - kSampleWeight); - - // The event count for the current or most recent sampling interval and - // the ordinal sampling interval they correspond to. - size_t events_ = 0; - int64_t events_sampling_interval_; - - // The so-far accrued average to |events_sampling_interval_|. - double decayed_average_ = 0.0; - }; - - // Exposed for use in tests. - struct Configuration; - - // Returns a new instance if this invocation has been sampled for quota - // checking. - static scoped_refptr MaybeCreate(); - - // Public for base::MakeRefCounted(). Use MaybeCreate(). - MessageQuotaChecker(const Configuration* config, - base::PassKey); - - // Call before writing a message to |message_pipe_|. - void BeforeWrite(); - - // Call before queueing |num| messages. - void BeforeMessagesEnqueued(size_t num); - // Call after de-queueing |num| messages. - void AfterMessagesDequeued(size_t num); - - // Returns the high watermark of quota usage observed by this instance. - size_t GetMaxQuotaUsage(); - - // Set or unset the message pipe associated with this quota checker. - void SetMessagePipe(MessagePipeHandle message_pipe); - - // Test support. - size_t GetCurrentQuotaStatusForTesting(); - static Configuration GetConfigurationForTesting(); - static scoped_refptr MaybeCreateForTesting( - const Configuration& config); - - private: - friend class base::RefCountedThreadSafe; - ~MessageQuotaChecker(); - static Configuration GetConfiguration(); - static scoped_refptr MaybeCreateImpl( - const Configuration& config); - - // Returns the amount of unread message quota currently used if there is - // an associated message pipe. - absl::optional GetCurrentMessagePipeQuota(); - void QuotaCheckImpl(size_t num_enqueued); - - raw_ptr config_; - - // The time ticks when this instance was created. - const base::TimeTicks creation_time_; - - - // Cumulative counts for the number of messages enqueued with - // |BeforeMessagesEnqueued()| and dequeued with |BeforeMessagesDequeued()|. - std::atomic messages_enqueued_{0}; - std::atomic messages_dequeued_{0}; - std::atomic messages_written_{0}; - - // Guards all state below here. - base::Lock lock_; - - // A decaying average of the rate of call to BeforeWrite per second. - DecayingRateAverage write_rate_average_ GUARDED_BY(lock_); - - // The locally consumed quota, e.g. the difference between the counts passed - // to |BeforeMessagesEnqueued()| and |BeforeMessagesDequeued()|. - size_t consumed_quota_ GUARDED_BY(lock_) = 0u; - // The high watermark consumed quota observed. - size_t max_consumed_quota_ GUARDED_BY(lock_) = 0u; - // The message pipe this instance observes, if any. - MessagePipeHandle message_pipe_ GUARDED_BY(lock_); -}; - -struct MessageQuotaChecker::Configuration { - bool is_enabled = false; - size_t sample_rate = 0u; - size_t unread_message_count_quota = 0u; - size_t crash_threshold = 0u; - void (*maybe_crash_function)(size_t quota_used, - absl::optional message_pipe_quota_used, - int64_t seconds_since_construction, - double average_write_rate, - uint64_t messages_enqueued, - uint64_t messages_dequeued, - uint64_t messages_written); -}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_MESSAGE_QUOTA_CHECKER_H_ diff --git a/mojo/public/cpp/bindings/lib/multiplex_router.cc b/mojo/public/cpp/bindings/lib/multiplex_router.cc index d8dd91b88100ea..1ca2bbd0b6dc4e 100644 --- a/mojo/public/cpp/bindings/lib/multiplex_router.cc +++ b/mojo/public/cpp/bindings/lib/multiplex_router.cc @@ -22,7 +22,6 @@ #include "mojo/public/cpp/bindings/interface_endpoint_client.h" #include "mojo/public/cpp/bindings/interface_endpoint_controller.h" #include "mojo/public/cpp/bindings/lib/may_auto_lock.h" -#include "mojo/public/cpp/bindings/lib/message_quota_checker.h" #include "mojo/public/cpp/bindings/sequence_local_sync_event_watcher.h" namespace mojo { @@ -388,11 +387,6 @@ MultiplexRouter::MultiplexRouter( connector_.set_incoming_receiver(&dispatcher_); - scoped_refptr quota_checker = - internal::MessageQuotaChecker::MaybeCreate(); - if (quota_checker) - connector_.SetMessageQuotaChecker(std::move(quota_checker)); - if (primary_interface_name) { control_message_handler_.SetDescription(base::JoinString( {primary_interface_name, "[primary] PipeControlMessageHandler"}, " ")); diff --git a/mojo/public/cpp/bindings/tests/BUILD.gn b/mojo/public/cpp/bindings/tests/BUILD.gn index e7f1bfa9c22c31..160fb6077a38e9 100644 --- a/mojo/public/cpp/bindings/tests/BUILD.gn +++ b/mojo/public/cpp/bindings/tests/BUILD.gn @@ -34,7 +34,6 @@ source_set("tests") { "map_unittest.cc", "message_queue.cc", "message_queue.h", - "message_quota_checker_unittest.cc", "message_unittest.cc", "multiplex_router_unittest.cc", "native_struct_unittest.cc", diff --git a/mojo/public/cpp/bindings/tests/message_quota_checker_unittest.cc b/mojo/public/cpp/bindings/tests/message_quota_checker_unittest.cc deleted file mode 100644 index 4b22984055b6e2..00000000000000 --- a/mojo/public/cpp/bindings/tests/message_quota_checker_unittest.cc +++ /dev/null @@ -1,356 +0,0 @@ -// Copyright 2019 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/lib/message_quota_checker.h" - -#include "base/test/scoped_feature_list.h" -#include "base/test/task_environment.h" -#include "base/time/time.h" -#include "mojo/core/embedder/embedder.h" -#include "mojo/public/c/system/quota.h" -#include "mojo/public/cpp/bindings/features.h" -#include "mojo/public/cpp/system/message_pipe.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/abseil-cpp/absl/types/optional.h" - -namespace mojo { -namespace test { -namespace { - -class MessageQuotaCheckerTest : public testing::Test { - public: - MessageQuotaCheckerTest() { - EXPECT_EQ(nullptr, instance_); - instance_ = this; - } - ~MessageQuotaCheckerTest() override { - EXPECT_EQ(this, instance_); - instance_ = nullptr; - } - - protected: - using MessageQuotaChecker = internal::MessageQuotaChecker; - using Configuration = MessageQuotaChecker::Configuration; - - static constexpr base::TimeDelta kOneSamplingInterval = - MessageQuotaChecker::DecayingRateAverage::kSamplingInterval; - - void Advance(base::TimeDelta delta) { - task_environment_.FastForwardBy(delta); - } - - static void RecordDumpAttempt(size_t total_quota_used, - absl::optional message_pipe_quota_used, - int64_t seconds_since_construction, - double average_write_rate, - uint64_t messages_enqueued, - uint64_t messages_dequeued, - uint64_t messages_written) { - ++instance_->num_dumps_; - instance_->last_dump_total_quota_used_ = total_quota_used; - instance_->last_dump_message_pipe_quota_used_ = message_pipe_quota_used; - instance_->last_seconds_since_construction_ = seconds_since_construction; - instance_->last_average_write_rate_ = average_write_rate; - instance_->last_messages_enqueued_ = messages_enqueued; - instance_->last_messages_dequeued_ = messages_dequeued; - instance_->last_messages_written_ = messages_written; - } - - // Mock time to allow testing - base::test::TaskEnvironment task_environment_{ - base::test::TaskEnvironment::TimeSource::MOCK_TIME}; - - size_t num_dumps_ = false; - size_t last_dump_total_quota_used_ = 0u; - absl::optional last_dump_message_pipe_quota_used_; - int64_t last_seconds_since_construction_ = 0; - double last_average_write_rate_ = 0.0; - uint64_t last_messages_enqueued_ = 0u; - uint64_t last_messages_dequeued_ = 0u; - uint64_t last_messages_written_ = 0u; - - static const Configuration enabled_config_; - - static MessageQuotaCheckerTest* instance_; -}; - -constexpr base::TimeDelta MessageQuotaCheckerTest::kOneSamplingInterval; -const MessageQuotaCheckerTest::Configuration - MessageQuotaCheckerTest::enabled_config_ = {true, 1, 100, 200, - &RecordDumpAttempt}; -MessageQuotaCheckerTest* MessageQuotaCheckerTest::instance_ = nullptr; - -TEST_F(MessageQuotaCheckerTest, ReadsConfigurationFromFeatures) { - if (mojo::core::IsMojoIpczEnabled()) { - GTEST_SKIP() << "Mojo quota APIs are not supported by MojoIpcz."; - } - - base::FieldTrialParams params; - params["SampleRate"] = "19"; - // Quota value parameter below the minimum the checker will allow. - params["QuotaValue"] = "57"; - params["CrashThreshold"] = "225"; - - base::test::ScopedFeatureList feature_list; - feature_list.InitAndEnableFeatureWithParameters( - features::kMojoRecordUnreadMessageCount, params); - - // Validate that the configuration reads from the feature configuration. - const MessageQuotaChecker::Configuration config = - MessageQuotaChecker::GetConfigurationForTesting(); - - EXPECT_TRUE(config.is_enabled); - EXPECT_EQ(19u, config.sample_rate); - EXPECT_EQ(100u, config.unread_message_count_quota); - EXPECT_EQ(225u, config.crash_threshold); - EXPECT_NE(nullptr, config.maybe_crash_function); -} - -TEST_F(MessageQuotaCheckerTest, DisabledByDefault) { - if (mojo::core::IsMojoIpczEnabled()) { - GTEST_SKIP() << "Mojo quota APIs are not supported by MojoIpcz."; - } - - const MessageQuotaChecker::Configuration config = - MessageQuotaChecker::GetConfigurationForTesting(); - EXPECT_FALSE(config.is_enabled); - - // Validate that no MessageQuoteCheckers are created in the default feature - // configuration. Run a bunch of iterations, as this function returns an - // instance randomly. - for (size_t i = 0; i < 1000; ++i) - ASSERT_EQ(nullptr, MessageQuotaChecker::MaybeCreate()); -} - -TEST_F(MessageQuotaCheckerTest, CreatesWhenEnabled) { - if (mojo::core::IsMojoIpczEnabled()) { - GTEST_SKIP() << "Mojo quota APIs are not supported by MojoIpcz."; - } - - // Run a bunch of iterations, as this function returns an instance randomly. - for (size_t i = 0; i < 1000; ++i) - EXPECT_NE(nullptr, - MessageQuotaChecker::MaybeCreateForTesting(enabled_config_)); -} - -TEST_F(MessageQuotaCheckerTest, CountsRight) { - if (mojo::core::IsMojoIpczEnabled()) { - GTEST_SKIP() << "Mojo quota APIs are not supported by MojoIpcz."; - } - - scoped_refptr checker = - MessageQuotaChecker::MaybeCreateForTesting(enabled_config_); - - ASSERT_EQ(0u, checker->GetCurrentQuotaStatusForTesting()); - ASSERT_EQ(0u, checker->GetMaxQuotaUsage()); - - checker->BeforeMessagesEnqueued(10); - ASSERT_EQ(10u, checker->GetCurrentQuotaStatusForTesting()); - ASSERT_EQ(10u, checker->GetMaxQuotaUsage()); - - checker->AfterMessagesDequeued(5); - ASSERT_EQ(5u, checker->GetCurrentQuotaStatusForTesting()); - ASSERT_EQ(10u, checker->GetMaxQuotaUsage()); - - ASSERT_EQ(0u, num_dumps_); -} - -TEST_F(MessageQuotaCheckerTest, CountsMessagePipeAlso) { - if (mojo::core::IsMojoIpczEnabled()) { - GTEST_SKIP() << "Mojo quota APIs are not supported by MojoIpcz."; - } - - MessagePipe pipe; - scoped_refptr checker = - MessageQuotaChecker::MaybeCreateForTesting(enabled_config_); - - uint64_t limit = 0; - uint64_t usage = 0; - MojoResult rv = MojoQueryQuota(pipe.handle0.get().value(), - MOJO_QUOTA_TYPE_UNREAD_MESSAGE_COUNT, nullptr, - &limit, &usage); - ASSERT_EQ(MOJO_RESULT_OK, rv); - ASSERT_EQ(MOJO_QUOTA_LIMIT_NONE, limit); - - checker->SetMessagePipe(pipe.handle0.get()); - - // Validate that the checker sets an unread message quota on the pipe, and - // that it clamps to the minimum of 100. - rv = MojoQueryQuota(pipe.handle0.get().value(), - MOJO_QUOTA_TYPE_UNREAD_MESSAGE_COUNT, nullptr, &limit, - &usage); - ASSERT_EQ(MOJO_RESULT_OK, rv); - ASSERT_EQ(100u, limit); - - ASSERT_EQ(0u, checker->GetCurrentQuotaStatusForTesting()); - - const char kMessage[] = "hello"; - for (size_t i = 0; i < 10; ++i) { - checker->BeforeWrite(); - ASSERT_EQ(MOJO_RESULT_OK, - WriteMessageRaw(pipe.handle0.get(), kMessage, sizeof(kMessage), - nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE)); - } - - ASSERT_EQ(10u, checker->GetMaxQuotaUsage()); - ASSERT_EQ(10u, checker->GetCurrentQuotaStatusForTesting()); - - checker->BeforeMessagesEnqueued(10); - ASSERT_EQ(20u, checker->GetMaxQuotaUsage()); - ASSERT_EQ(20u, checker->GetCurrentQuotaStatusForTesting()); - - ASSERT_EQ(0u, num_dumps_); -} - -TEST_F(MessageQuotaCheckerTest, DumpsCoreOnOverrun) { - if (mojo::core::IsMojoIpczEnabled()) { - GTEST_SKIP() << "Mojo quota APIs are not supported by MojoIpcz."; - } - - // Make sure to start the test on an even sampling interval to get consistent - // average computations below. - base::TimeTicks t0 = MessageQuotaChecker::DecayingRateAverage:: - GetNextSamplingIntervalForTesting(base::TimeTicks::Now()); - task_environment_.AdvanceClock(t0 - base::TimeTicks::Now()); - - MessagePipe pipe; - scoped_refptr checker = - MessageQuotaChecker::MaybeCreateForTesting(enabled_config_); - - // Fast forward time by a few sampling intervals. - Advance(10 * kOneSamplingInterval); - - // Queue up 100 messages. - checker->SetMessagePipe(pipe.handle0.get()); - const char kMessage[] = "hello"; - for (size_t i = 0; i < 100; ++i) { - checker->BeforeWrite(); - ASSERT_EQ(MOJO_RESULT_OK, - WriteMessageRaw(pipe.handle0.get(), kMessage, sizeof(kMessage), - nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE)); - } - - // The crash threshold is at 200 per the config, so shouldn't have attempted - // a core dump yet. - ASSERT_EQ(0u, num_dumps_); - - checker->BeforeMessagesEnqueued(99); - ASSERT_EQ(0u, num_dumps_); - - Advance(kOneSamplingInterval); - checker->BeforeMessagesEnqueued(1); - EXPECT_EQ(1u, num_dumps_); - EXPECT_EQ(200u, last_dump_total_quota_used_); - EXPECT_EQ(100u, last_dump_message_pipe_quota_used_); - EXPECT_EQ((11 * kOneSamplingInterval).InSeconds(), - last_seconds_since_construction_); - EXPECT_EQ(50, last_average_write_rate_); - - checker->BeforeWrite(); - ASSERT_EQ(MOJO_RESULT_OK, - WriteMessageRaw(pipe.handle0.get(), kMessage, sizeof(kMessage), - nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE)); - - EXPECT_EQ(2u, num_dumps_); - EXPECT_EQ(201u, last_dump_total_quota_used_); - EXPECT_EQ(101u, last_dump_message_pipe_quota_used_); - EXPECT_EQ((11 * kOneSamplingInterval).InSeconds(), - last_seconds_since_construction_); - EXPECT_EQ(50, last_average_write_rate_); - - Advance(kOneSamplingInterval); - checker->SetMessagePipe(mojo::MessagePipeHandle()); - checker->AfterMessagesDequeued(50); - checker->BeforeMessagesEnqueued(300); - EXPECT_EQ(3u, num_dumps_); - EXPECT_EQ(350u, last_dump_total_quota_used_); - EXPECT_FALSE(last_dump_message_pipe_quota_used_.has_value()); - EXPECT_EQ((12 * kOneSamplingInterval).InSeconds(), - last_seconds_since_construction_); - EXPECT_EQ(25.5, last_average_write_rate_); - EXPECT_EQ(400u, last_messages_enqueued_); - EXPECT_EQ(50u, last_messages_dequeued_); - EXPECT_EQ(101u, last_messages_written_); -} - -TEST_F(MessageQuotaCheckerTest, DecayingRateAverage) { - if (mojo::core::IsMojoIpczEnabled()) { - GTEST_SKIP() << "Mojo quota APIs are not supported by MojoIpcz."; - } - - // Make sure to start the test on an even sampling interval to get consistent - // average computations below. - base::TimeTicks t0 = MessageQuotaChecker::DecayingRateAverage:: - GetNextSamplingIntervalForTesting(base::TimeTicks::Now()); - task_environment_.AdvanceClock(t0 - base::TimeTicks::Now()); - - // Walk time forward a bit from the epoch. - t0 += 101 * kOneSamplingInterval; - - MessageQuotaChecker::DecayingRateAverage avg; - EXPECT_EQ(0.0, avg.GetDecayedRateAverage(t0)); - - // Tally two events in the same sampling interval. - avg.AccrueEvent(t0); - avg.AccrueEvent(t0); - - // The decayed average rate is half of the rate this sampling interval. - t0 += kOneSamplingInterval; - EXPECT_EQ(1.0, avg.GetDecayedRateAverage(t0)); - - // Tally another two events in a subsequent sampling interval. - avg.AccrueEvent(t0); - avg.AccrueEvent(t0); - - t0 += kOneSamplingInterval; - EXPECT_EQ(1.5, avg.GetDecayedRateAverage(t0)); - - // Tally another two events in a subsequent sampling interval. - avg.AccrueEvent(t0); - avg.AccrueEvent(t0); - EXPECT_EQ(1.75, avg.GetDecayedRateAverage(t0 + kOneSamplingInterval)); - - // Make sure the average is decayed with time, including within a sampling - // interval. - EXPECT_EQ(0.875, avg.GetDecayedRateAverage(t0 + 2 * kOneSamplingInterval)); - EXPECT_NEAR(0.619, avg.GetDecayedRateAverage(t0 + 2.5 * kOneSamplingInterval), - 0.001); - EXPECT_EQ(0.4375, avg.GetDecayedRateAverage(t0 + 3 * kOneSamplingInterval)); - - t0 += 10 * kOneSamplingInterval; - avg.AccrueEvent(t0); - avg.AccrueEvent(t0); - // The previous average should have decayed by 1/1024. - EXPECT_EQ(1.0 + 1.75 / 1024.0, - avg.GetDecayedRateAverage(t0 + kOneSamplingInterval)); - - // Explicitly test simple interpolation in a sampling interval by setting - // up an average that's conveniently converged to 4.0. - MessageQuotaChecker::DecayingRateAverage avg2; - for (size_t i = 0; i < 16; ++i) - avg2.AccrueEvent(t0); - t0 += 2 * kOneSamplingInterval; - EXPECT_EQ(4.0, avg2.GetDecayedRateAverage(t0)); - - // Now test 0/8, 1/8, 1/4, 1/2 and 3/4-way interpolation. - avg2.AccrueEvent(t0); - // The special case of adding an event and requesting the average at the - // start of sampling interval explicitly excludes that event. - EXPECT_EQ(4.0, avg2.GetDecayedRateAverage(t0)); - EXPECT_NEAR(4.332, - avg2.GetDecayedRateAverage(t0 + 1.0 / 8.0 * kOneSamplingInterval), - 0.001); - EXPECT_EQ(4.0, - avg2.GetDecayedRateAverage(t0 + 1.0 / 4.0 * kOneSamplingInterval)); - avg2.AccrueEvent(t0); - EXPECT_EQ(4.0, - avg2.GetDecayedRateAverage(t0 + 2.0 / 4.0 * kOneSamplingInterval)); - avg2.AccrueEvent(t0); - EXPECT_EQ(4.0, - avg2.GetDecayedRateAverage(t0 + 3.0 / 4.0 * kOneSamplingInterval)); -} - -} // namespace -} // namespace test -} // namespace mojo