diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2017-07-12 14:07:37 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2017-07-17 10:29:26 +0000 |
commit | ec02ee4181c49b61fce1c8fb99292dbb8139cc90 (patch) | |
tree | 25cde714b2b71eb639d1cd53f5a22e9ba76e14ef /chromium/components/tracing | |
parent | bb09965444b5bb20b096a291445170876225268d (diff) | |
download | qtwebengine-chromium-ec02ee4181c49b61fce1c8fb99292dbb8139cc90.tar.gz |
BASELINE: Update Chromium to 59.0.3071.134
Change-Id: Id02ef6fb2204c5fd21668a1c3e6911c83b17585a
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'chromium/components/tracing')
11 files changed, 93 insertions, 688 deletions
diff --git a/chromium/components/tracing/BUILD.gn b/chromium/components/tracing/BUILD.gn index deab4a66a3d..8b0bd09b7ac 100644 --- a/chromium/components/tracing/BUILD.gn +++ b/chromium/components/tracing/BUILD.gn @@ -7,8 +7,6 @@ import("//third_party/protobuf/proto_library.gni") component("tracing") { sources = [ - "child/child_memory_dump_manager_delegate_impl.cc", - "child/child_memory_dump_manager_delegate_impl.h", "child/child_trace_message_filter.cc", "child/child_trace_message_filter.h", "common/graphics_memory_dump_provider_android.cc", @@ -101,6 +99,7 @@ source_set("unit_tests") { "core/trace_buffer_writer_unittest.cc", "core/trace_ring_buffer_unittest.cc", "test/fake_scattered_buffer.cc", + "test/fake_scattered_buffer.h", "test/proto_zero_generation_unittest.cc", ] diff --git a/chromium/components/tracing/child/child_memory_dump_manager_delegate_impl.cc b/chromium/components/tracing/child/child_memory_dump_manager_delegate_impl.cc deleted file mode 100644 index f0c4517b2ea..00000000000 --- a/chromium/components/tracing/child/child_memory_dump_manager_delegate_impl.cc +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/tracing/child/child_memory_dump_manager_delegate_impl.h" - -#include "base/single_thread_task_runner.h" -#include "build/build_config.h" -#include "components/tracing/child/child_trace_message_filter.h" -#include "components/tracing/common/process_metrics_memory_dump_provider.h" - -namespace tracing { - -namespace { -void AbortDumpRequest(const base::trace_event::MemoryDumpRequestArgs& args, - const base::trace_event::MemoryDumpCallback& callback) { - if (!callback.is_null()) - callback.Run(args.dump_guid, false /* success */); -} -} // namespace - -// static -ChildMemoryDumpManagerDelegateImpl* -ChildMemoryDumpManagerDelegateImpl::GetInstance() { - return base::Singleton< - ChildMemoryDumpManagerDelegateImpl, - base::LeakySingletonTraits<ChildMemoryDumpManagerDelegateImpl>>::get(); -} - -ChildMemoryDumpManagerDelegateImpl::ChildMemoryDumpManagerDelegateImpl() - : ctmf_(nullptr), - tracing_process_id_( - base::trace_event::MemoryDumpManager::kInvalidTracingProcessId) { -} - -ChildMemoryDumpManagerDelegateImpl::~ChildMemoryDumpManagerDelegateImpl() {} - -void ChildMemoryDumpManagerDelegateImpl::SetChildTraceMessageFilter( - ChildTraceMessageFilter* ctmf) { - auto* task_runner = ctmf ? (ctmf->ipc_task_runner()) : nullptr; - // Check that we are either registering the CTMF or tearing it down, but not - // replacing a valid instance with another one (should never happen). - DCHECK(!ctmf_ || (!ctmf && ctmf_task_runner_)); - ctmf_ = ctmf; - - { - base::AutoLock lock(lock_); - ctmf_task_runner_ = task_runner; - } - - if (ctmf) { - base::trace_event::MemoryDumpManager::GetInstance()->Initialize( - this /* delegate */, false /* is_coordinator */); - -#if !defined(OS_LINUX) && !defined(OS_NACL) - // On linux the browser process takes care of dumping process metrics. - // The child process is not allowed to do so due to BPF sandbox. - tracing::ProcessMetricsMemoryDumpProvider::RegisterForProcess( - base::kNullProcessId); -#endif - } -} - -// Invoked in child processes by the MemoryDumpManager. -void ChildMemoryDumpManagerDelegateImpl::RequestGlobalMemoryDump( - const base::trace_event::MemoryDumpRequestArgs& args, - const base::trace_event::MemoryDumpCallback& callback) { - // RequestGlobalMemoryDump can be called on any thread, cannot access - // ctmf_task_runner_ as it could be racy. - scoped_refptr<base::SingleThreadTaskRunner> ctmf_task_runner; - { - base::AutoLock lock(lock_); - ctmf_task_runner = ctmf_task_runner_; - } - - // Bail out if we receive a dump request from the manager before the - // ChildTraceMessageFilter has been initialized. - if (!ctmf_task_runner) { - VLOG(1) << base::trace_event::MemoryDumpManager::kLogPrefix - << " failed because child trace message filter hasn't been" - << " initialized"; - return AbortDumpRequest(args, callback); - } - - // Make sure we access |ctmf_| only on the thread where it lives to avoid - // races on shutdown. - if (!ctmf_task_runner->BelongsToCurrentThread()) { - const bool did_post_task = ctmf_task_runner->PostTask( - FROM_HERE, - base::Bind(&ChildMemoryDumpManagerDelegateImpl::RequestGlobalMemoryDump, - base::Unretained(this), args, callback)); - if (!did_post_task) - return AbortDumpRequest(args, callback); - return; - } - - // The ChildTraceMessageFilter could have been destroyed while hopping on the - // right thread. If this is the case, bail out. - if (!ctmf_) { - VLOG(1) << base::trace_event::MemoryDumpManager::kLogPrefix - << " failed because child trace message filter was" - << " destroyed while switching threads"; - return AbortDumpRequest(args, callback); - } - - // Send the request up to the browser process' MessageDumpmanager. - ctmf_->SendGlobalMemoryDumpRequest(args, callback); -} - -uint64_t ChildMemoryDumpManagerDelegateImpl::GetTracingProcessId() const { - return tracing_process_id_; -} - -} // namespace tracing diff --git a/chromium/components/tracing/child/child_memory_dump_manager_delegate_impl.h b/chromium/components/tracing/child/child_memory_dump_manager_delegate_impl.h deleted file mode 100644 index fc27d96f279..00000000000 --- a/chromium/components/tracing/child/child_memory_dump_manager_delegate_impl.h +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_TRACING_CHILD_CHILD_MEMORY_DUMP_MANAGER_DELEGATE_IMPL_H_ -#define COMPONENTS_TRACING_CHILD_CHILD_MEMORY_DUMP_MANAGER_DELEGATE_IMPL_H_ - -#include "base/trace_event/memory_dump_manager.h" - -#include <stdint.h> - -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/memory/singleton.h" -#include "base/synchronization/lock.h" -#include "components/tracing/tracing_export.h" - -namespace base { -class SingleThreadTaskRunner; -} // namespace base - -namespace tracing { - -class ChildTraceMessageFilter; - -// This class is a simple proxy class between the MemoryDumpManager and the -// ChildTraceMessageFilter. It's only purpose is to adapt the lifetime of -// CTMF to the demands of MDM, which expects the delegate to be thread-safe -// and long lived. CTMF, instead, can be torn down during browser shutdown. -// This class is registered as MDM delegate in child processes and handles -// gracefully (and thread-safely) failures in the case of a lack of the CTMF. -class TRACING_EXPORT ChildMemoryDumpManagerDelegateImpl - : public base::trace_event::MemoryDumpManagerDelegate { - public: - static ChildMemoryDumpManagerDelegateImpl* GetInstance(); - - // base::trace_event::MemoryDumpManagerDelegate implementation. - void RequestGlobalMemoryDump( - const base::trace_event::MemoryDumpRequestArgs& args, - const base::trace_event::MemoryDumpCallback& callback) override; - uint64_t GetTracingProcessId() const override; - - void SetChildTraceMessageFilter(ChildTraceMessageFilter* ctmf); - - // Pass kInvalidTracingProcessId to invalidate the id. - void set_tracing_process_id(uint64_t id) { - DCHECK(tracing_process_id_ == - base::trace_event::MemoryDumpManager::kInvalidTracingProcessId || - id == - base::trace_event::MemoryDumpManager::kInvalidTracingProcessId || - id == tracing_process_id_); - tracing_process_id_ = id; - } - - protected: - // Make CreateProcessDump() visible to ChildTraceMessageFilter. - friend class ChildTraceMessageFilter; - - private: - friend struct base::DefaultSingletonTraits< - ChildMemoryDumpManagerDelegateImpl>; - - ChildMemoryDumpManagerDelegateImpl(); - ~ChildMemoryDumpManagerDelegateImpl() override; - - ChildTraceMessageFilter* ctmf_; // Not owned. - - // The SingleThreadTaskRunner where the |ctmf_| lives. - // It is NULL iff |cmtf_| is NULL. - scoped_refptr<base::SingleThreadTaskRunner> ctmf_task_runner_; - - // Protects from concurrent access to |ctmf_task_runner_| to allow - // RequestGlobalMemoryDump to be called from arbitrary threads. - base::Lock lock_; - - // The unique id of the child process, created for tracing and is expected to - // be valid only when tracing is enabled. - uint64_t tracing_process_id_; - - DISALLOW_COPY_AND_ASSIGN(ChildMemoryDumpManagerDelegateImpl); -}; - -} // namespace tracing - -#endif // COMPONENTS_TRACING_CHILD_CHILD_MEMORY_DUMP_MANAGER_DELEGATE_IMPL_H_ diff --git a/chromium/components/tracing/child/child_trace_message_filter.cc b/chromium/components/tracing/child/child_trace_message_filter.cc index ed2be875c7d..2cd76dc7b2a 100644 --- a/chromium/components/tracing/child/child_trace_message_filter.cc +++ b/chromium/components/tracing/child/child_trace_message_filter.cc @@ -8,11 +8,13 @@ #include "base/memory/ref_counted_memory.h" #include "base/metrics/statistics_recorder.h" +#include "base/trace_event/memory_dump_manager.h" #include "base/trace_event/trace_event.h" -#include "components/tracing/child/child_memory_dump_manager_delegate_impl.h" +#include "components/tracing/common/process_metrics_memory_dump_provider.h" #include "components/tracing/common/tracing_messages.h" #include "ipc/ipc_channel.h" +using base::trace_event::MemoryDumpManager; using base::trace_event::TraceLog; namespace tracing { @@ -25,16 +27,20 @@ const int kMinTimeBetweenHistogramChangesInSeconds = 10; ChildTraceMessageFilter::ChildTraceMessageFilter( base::SingleThreadTaskRunner* ipc_task_runner) - : sender_(NULL), - ipc_task_runner_(ipc_task_runner), - pending_memory_dump_guid_(0) { -} + : enabled_tracing_modes_(0), + sender_(NULL), + ipc_task_runner_(ipc_task_runner) {} void ChildTraceMessageFilter::OnFilterAdded(IPC::Channel* channel) { sender_ = channel; sender_->Send(new TracingHostMsg_ChildSupportsTracing()); - ChildMemoryDumpManagerDelegateImpl::GetInstance()->SetChildTraceMessageFilter( - this); + +#if !defined(OS_LINUX) && !defined(OS_NACL) + // On linux the browser process takes care of dumping process metrics. + // The child process is not allowed to do so due to BPF sandbox. + tracing::ProcessMetricsMemoryDumpProvider::RegisterForProcess( + base::kNullProcessId); +#endif } void ChildTraceMessageFilter::SetSenderForTesting(IPC::Sender* sender) { @@ -42,8 +48,6 @@ void ChildTraceMessageFilter::SetSenderForTesting(IPC::Sender* sender) { } void ChildTraceMessageFilter::OnFilterRemoved() { - ChildMemoryDumpManagerDelegateImpl::GetInstance()->SetChildTraceMessageFilter( - nullptr); sender_ = NULL; } @@ -54,10 +58,6 @@ bool ChildTraceMessageFilter::OnMessageReceived(const IPC::Message& message) { IPC_MESSAGE_HANDLER(TracingMsg_EndTracing, OnEndTracing) IPC_MESSAGE_HANDLER(TracingMsg_CancelTracing, OnCancelTracing) IPC_MESSAGE_HANDLER(TracingMsg_GetTraceLogStatus, OnGetTraceLogStatus) - IPC_MESSAGE_HANDLER(TracingMsg_ProcessMemoryDumpRequest, - OnProcessMemoryDumpRequest) - IPC_MESSAGE_HANDLER(TracingMsg_GlobalMemoryDumpResponse, - OnGlobalMemoryDumpResponse) IPC_MESSAGE_HANDLER(TracingMsg_SetUMACallback, OnSetUMACallback) IPC_MESSAGE_HANDLER(TracingMsg_ClearUMACallback, OnClearUMACallback) IPC_MESSAGE_UNHANDLED(handled = false) @@ -78,15 +78,18 @@ void ChildTraceMessageFilter::OnBeginTracing( base::TimeDelta time_offset = base::TimeTicks::Now() - browser_time; TraceLog::GetInstance()->SetTimeOffset(time_offset); #endif - ChildMemoryDumpManagerDelegateImpl::GetInstance()->set_tracing_process_id( - tracing_process_id); - TraceLog::GetInstance()->SetEnabled( - base::trace_event::TraceConfig(trace_config_str), - base::trace_event::TraceLog::RECORDING_MODE); + MemoryDumpManager::GetInstance()->set_tracing_process_id(tracing_process_id); + const base::trace_event::TraceConfig trace_config(trace_config_str); + enabled_tracing_modes_ = base::trace_event::TraceLog::RECORDING_MODE; + if (!trace_config.event_filters().empty()) + enabled_tracing_modes_ |= base::trace_event::TraceLog::FILTERING_MODE; + TraceLog::GetInstance()->SetEnabled(trace_config, enabled_tracing_modes_); } void ChildTraceMessageFilter::OnEndTracing() { - TraceLog::GetInstance()->SetDisabled(); + DCHECK(enabled_tracing_modes_); + TraceLog::GetInstance()->SetDisabled(enabled_tracing_modes_); + enabled_tracing_modes_ = 0; // Flush will generate one or more callbacks to OnTraceDataCollected // synchronously or asynchronously. EndTracingAck will be sent in the last @@ -95,8 +98,8 @@ void ChildTraceMessageFilter::OnEndTracing() { TraceLog::GetInstance()->Flush( base::Bind(&ChildTraceMessageFilter::OnTraceDataCollected, this)); - ChildMemoryDumpManagerDelegateImpl::GetInstance()->set_tracing_process_id( - base::trace_event::MemoryDumpManager::kInvalidTracingProcessId); + MemoryDumpManager::GetInstance()->set_tracing_process_id( + MemoryDumpManager::kInvalidTracingProcessId); } void ChildTraceMessageFilter::OnCancelTracing() { @@ -129,52 +132,6 @@ void ChildTraceMessageFilter::OnTraceDataCollected( } } -// Sent by the Browser's MemoryDumpManager when coordinating a global dump. -void ChildTraceMessageFilter::OnProcessMemoryDumpRequest( - const base::trace_event::MemoryDumpRequestArgs& args) { - ChildMemoryDumpManagerDelegateImpl::GetInstance()->CreateProcessDump( - args, - base::Bind(&ChildTraceMessageFilter::OnProcessMemoryDumpDone, this)); -} - -void ChildTraceMessageFilter::OnProcessMemoryDumpDone(uint64_t dump_guid, - bool success) { - sender_->Send( - new TracingHostMsg_ProcessMemoryDumpResponse(dump_guid, success)); -} - -// Initiates a dump request, asking the Browser's MemoryDumpManager to -// coordinate a global memory dump. The Browser's MDM will answer back with a -// MemoryDumpResponse when all the child processes (including this one) have -// dumped, or with a NACK (|success| == false) if the dump failed (e.g., due to -// a collision with a concurrent request from another child process). -void ChildTraceMessageFilter::SendGlobalMemoryDumpRequest( - const base::trace_event::MemoryDumpRequestArgs& args, - const base::trace_event::MemoryDumpCallback& callback) { - // If there is already another dump request pending from this child process, - // there is no point bothering the Browser's MemoryDumpManager. - if (pending_memory_dump_guid_) { - if (!callback.is_null()) - callback.Run(args.dump_guid, false); - return; - } - - pending_memory_dump_guid_ = args.dump_guid; - pending_memory_dump_callback_ = callback; - sender_->Send(new TracingHostMsg_GlobalMemoryDumpRequest(args)); -} - -// Sent by the Browser's MemoryDumpManager in response of a dump request -// initiated by this child process. -void ChildTraceMessageFilter::OnGlobalMemoryDumpResponse(uint64_t dump_guid, - bool success) { - DCHECK_NE(0U, pending_memory_dump_guid_); - pending_memory_dump_guid_ = 0; - if (pending_memory_dump_callback_.is_null()) - return; - pending_memory_dump_callback_.Run(dump_guid, success); -} - void ChildTraceMessageFilter::OnHistogramChanged( const std::string& histogram_name, base::Histogram::Sample reference_lower_value, diff --git a/chromium/components/tracing/child/child_trace_message_filter.h b/chromium/components/tracing/child/child_trace_message_filter.h index 287abd3503d..929fa7e21cd 100644 --- a/chromium/components/tracing/child/child_trace_message_filter.h +++ b/chromium/components/tracing/child/child_trace_message_filter.h @@ -12,7 +12,6 @@ #include "base/memory/ref_counted_memory.h" #include "base/metrics/histogram.h" #include "base/time/time.h" -#include "base/trace_event/memory_dump_request_args.h" #include "components/tracing/tracing_export.h" #include "ipc/message_filter.h" @@ -33,10 +32,6 @@ class TRACING_EXPORT ChildTraceMessageFilter : public IPC::MessageFilter { void OnFilterRemoved() override; bool OnMessageReceived(const IPC::Message& message) override; - void SendGlobalMemoryDumpRequest( - const base::trace_event::MemoryDumpRequestArgs& args, - const base::trace_event::MemoryDumpCallback& callback); - base::SingleThreadTaskRunner* ipc_task_runner() const { return ipc_task_runner_; } @@ -58,9 +53,6 @@ class TRACING_EXPORT ChildTraceMessageFilter : public IPC::MessageFilter { const std::string& event_name); void OnCancelWatchEvent(); void OnWatchEventMatched(); - void OnProcessMemoryDumpRequest( - const base::trace_event::MemoryDumpRequestArgs& args); - void OnGlobalMemoryDumpResponse(uint64_t dump_guid, bool success); void OnSetUMACallback(const std::string& histogram_name, int histogram_lower_value, int histogram_upper_value, @@ -79,20 +71,13 @@ class TRACING_EXPORT ChildTraceMessageFilter : public IPC::MessageFilter { const scoped_refptr<base::RefCountedString>& events_str_ptr, bool has_more_events); - void OnProcessMemoryDumpDone(uint64_t dump_guid, bool success); - void SetSenderForTesting(IPC::Sender* sender); + uint8_t enabled_tracing_modes_; + IPC::Sender* sender_; base::SingleThreadTaskRunner* ipc_task_runner_; - // guid of the outstanding request (to the Browser's MemoryDumpManager), if - // any. 0 if there is no request pending. - uint64_t pending_memory_dump_guid_; - - // callback of the outstanding memory dump request, if any. - base::trace_event::MemoryDumpCallback pending_memory_dump_callback_; - base::Time histogram_last_changed_; DISALLOW_COPY_AND_ASSIGN(ChildTraceMessageFilter); diff --git a/chromium/components/tracing/child/child_trace_message_filter_browsertest.cc b/chromium/components/tracing/child/child_trace_message_filter_browsertest.cc deleted file mode 100644 index d0d2d020a88..00000000000 --- a/chromium/components/tracing/child/child_trace_message_filter_browsertest.cc +++ /dev/null @@ -1,326 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <stdint.h> - -#include <memory> -#include <tuple> - -#include "base/callback.h" -#include "base/run_loop.h" -#include "base/threading/thread_task_runner_handle.h" -#include "base/trace_event/memory_dump_manager.h" -#include "base/trace_event/memory_dump_provider.h" -#include "base/trace_event/trace_event.h" -#include "components/tracing/child/child_memory_dump_manager_delegate_impl.h" -#include "components/tracing/child/child_trace_message_filter.h" -#include "components/tracing/common/tracing_messages.h" -#include "content/public/test/render_view_test.h" -#include "testing/gmock/include/gmock/gmock.h" - -using base::trace_event::MemoryDumpManager; -using base::trace_event::MemoryDumpRequestArgs; -using base::trace_event::MemoryDumpArgs; -using base::trace_event::MemoryDumpLevelOfDetail; -using base::trace_event::MemoryDumpType; -using testing::_; -using testing::Return; - -namespace tracing { - -// A mock dump provider, used to check that dump requests actually end up -// creating memory dumps. -class MockDumpProvider : public base::trace_event::MemoryDumpProvider { - public: - MOCK_METHOD2(OnMemoryDump, - bool(const MemoryDumpArgs& args, - base::trace_event::ProcessMemoryDump* pmd)); -}; - -class ChildTracingTest : public content::RenderViewTest, public IPC::Listener { - public: - // Used as callback argument for MemoryDumpManager::RequestGlobalDump(): - void OnMemoryDumpCallback(uint64_t dump_guid, bool status) { - last_callback_dump_guid_ = dump_guid; - last_callback_status_ = status; - ++callback_call_count_; - } - - protected: - void SetUp() override { - // RenderViewTest::SetUp causes additional registrations, so we first - // register the mock dump provider and ignore registrations from then on. - // In addition to the mock dump provider, the TraceLog has already - // registered itself by now; this cannot be prevented easily. - mock_dump_provider_.reset(new MockDumpProvider()); - MemoryDumpManager::GetInstance()->RegisterDumpProvider( - mock_dump_provider_.get(), "MockDumpProvider", - base::ThreadTaskRunnerHandle::Get()); - MemoryDumpManager::GetInstance() - ->set_dumper_registrations_ignored_for_testing(true); - - RenderViewTest::SetUp(); - - callback_call_count_ = 0; - last_callback_dump_guid_ = 0; - last_callback_status_ = false; - wait_for_ipc_message_type_ = 0; - callback_ = base::Bind(&ChildTracingTest::OnMemoryDumpCallback, - base::Unretained(this)); - task_runner_ = base::ThreadTaskRunnerHandle::Get(); - ctmf_ = make_scoped_refptr(new ChildTraceMessageFilter(task_runner_.get())); - render_thread_->AddFilter(ctmf_.get()); - - // Add a filter to the TestSink which allows to WaitForIPCMessage() by - // posting a nested RunLoop closure when a given IPC Message is seen. - render_thread_->sink().AddFilter(this); - - // Getting an instance of |ChildMemoryDumpManagerDelegateImpl| calls - // |MemoryDumpManager::Initialize| with the correct delegate. - ChildMemoryDumpManagerDelegateImpl::GetInstance(); - } - - void TearDown() override { - render_thread_->sink().RemoveFilter(this); - RenderViewTest::TearDown(); - MemoryDumpManager::GetInstance()->UnregisterDumpProvider( - mock_dump_provider_.get()); - mock_dump_provider_.reset(); - ctmf_ = nullptr; - task_runner_ = nullptr; - } - - // IPC::Filter implementation. - bool OnMessageReceived(const IPC::Message& message) override { - if (message.type() == wait_for_ipc_message_type_) { - DCHECK(!wait_for_ipc_closure_.is_null()); - task_runner_->PostTask(FROM_HERE, wait_for_ipc_closure_); - } - // Always propagate messages to the sink, never consume them here. - return false; - } - - const IPC::Message* WaitForIPCMessage(uint32_t message_type) { - base::RunLoop run_loop; - wait_for_ipc_message_type_ = message_type; - wait_for_ipc_closure_ = run_loop.QuitClosure(); - run_loop.Run(); - wait_for_ipc_message_type_ = 0; - wait_for_ipc_closure_.Reset(); - return render_thread_->sink().GetUniqueMessageMatching(message_type); - } - - // Simulates a synthetic browser -> child (this process) IPC message. - void SimulateSyntheticMessageFromBrowser(const IPC::Message& msg) { - ctmf_->OnMessageReceived(msg); - } - - void EnableTracingWithMemoryDumps() { - // Re-enabling tracing could crash these tests https://crbug.com/656729 . - if (base::trace_event::TraceLog::GetInstance()->IsEnabled()) { - FAIL() << "Tracing seems to be already enabled. " - "Very likely this is because the startup tracing file " - "has been leaked from a previous test."; - } - - std::string category_filter = "-*,"; // Disable all other trace categories. - category_filter += MemoryDumpManager::kTraceCategory; - base::trace_event::TraceConfig trace_config(category_filter, ""); - TracingMsg_BeginTracing msg(trace_config.ToString(), base::TimeTicks(), 0); - SimulateSyntheticMessageFromBrowser(msg); - } - - void DisableTracing() { - SimulateSyntheticMessageFromBrowser(TracingMsg_EndTracing()); - } - - // Simulates a synthetic browser -> child process memory dump request and - // checks that the child actually sends a response to that. - void RequestProcessMemoryDumpAndCheckResponse(uint64_t dump_guid) { - SimulateSyntheticMessageFromBrowser(TracingMsg_ProcessMemoryDumpRequest( - {dump_guid, MemoryDumpType::EXPLICITLY_TRIGGERED, - MemoryDumpLevelOfDetail::DETAILED})); - - // Check that a child -> browser response to the local dump request is sent. - const IPC::Message* msg = - WaitForIPCMessage(TracingHostMsg_ProcessMemoryDumpResponse::ID); - EXPECT_NE(nullptr, msg); - - // Check that the |dump_guid| and the |success| fields are properly set. - TracingHostMsg_ProcessMemoryDumpResponse::Param params; - TracingHostMsg_ProcessMemoryDumpResponse::Read(msg, ¶ms); - const uint64_t resp_guid = std::get<0>(params); - const bool resp_success = std::get<1>(params); - EXPECT_EQ(dump_guid, resp_guid); - EXPECT_TRUE(resp_success); - } - - // Retrieves the MemoryDumpRequestArgs of the global memory dump request that - // this child process tried to send to the browser. Fails if either none or - // multiple requests were sent. - MemoryDumpRequestArgs GetInterceptedGlobalMemoryDumpRequest() { - const IPC::Message* msg = render_thread_->sink().GetUniqueMessageMatching( - TracingHostMsg_GlobalMemoryDumpRequest::ID); - EXPECT_NE(nullptr, msg); - TracingHostMsg_GlobalMemoryDumpRequest::Param params; - TracingHostMsg_GlobalMemoryDumpRequest::Read(msg, ¶ms); - MemoryDumpRequestArgs args = std::get<0>(params); - EXPECT_NE(0U, args.dump_guid); - return args; - } - - scoped_refptr<ChildTraceMessageFilter> ctmf_; - std::unique_ptr<MockDumpProvider> mock_dump_provider_; - scoped_refptr<base::SingleThreadTaskRunner> task_runner_; - base::trace_event::MemoryDumpCallback callback_; - uint32_t wait_for_ipc_message_type_; - base::Closure wait_for_ipc_closure_; - uint32_t callback_call_count_; - uint64_t last_callback_dump_guid_; - bool last_callback_status_; -}; - -// Covers the case of some browser-initiated memory dumps. -#if defined(OS_ANDROID) -// Flaky on Android. http://crbug.com/620734. -#define MAYBE_BrowserInitiatedMemoryDumps DISABLED_BrowserInitiatedMemoryDumps -#else -#define MAYBE_BrowserInitiatedMemoryDumps BrowserInitiatedMemoryDumps -#endif -TEST_F(ChildTracingTest, MAYBE_BrowserInitiatedMemoryDumps) { - const uint32_t kNumDumps = 3; - - EnableTracingWithMemoryDumps(); - EXPECT_CALL(*mock_dump_provider_, OnMemoryDump(_, _)) - .Times(kNumDumps) - .WillRepeatedly(Return(true)); - - for (uint32_t i = 0; i < kNumDumps; ++i) { - render_thread_->sink().ClearMessages(); - RequestProcessMemoryDumpAndCheckResponse(i + 1); - } - - DisableTracing(); -} - -// Covers the case of one simple child-initiated memory dump without callback, -// simulating a global memory dump request to the browser (+ response). -TEST_F(ChildTracingTest, SingleChildInitiatedMemoryDump) { - EnableTracingWithMemoryDumps(); - - // Expect that our mock dump provider is called when the emulated memory dump - // request (browser -> child) is sent. - EXPECT_CALL(*mock_dump_provider_, OnMemoryDump(_, _)) - .Times(1) - .WillRepeatedly(Return(true)); - - // Send the global memory dump request to the browser. - render_thread_->sink().ClearMessages(); - MemoryDumpManager::GetInstance()->RequestGlobalDump( - MemoryDumpType::EXPLICITLY_TRIGGERED, MemoryDumpLevelOfDetail::DETAILED); - base::RunLoop().RunUntilIdle(); - - // Check that the child -> browser global dump request IPC is actually sent. - MemoryDumpRequestArgs args = GetInterceptedGlobalMemoryDumpRequest(); - EXPECT_EQ(MemoryDumpType::EXPLICITLY_TRIGGERED, args.dump_type); - - // Emulate a browser -> child process dump request and corresponding response. - RequestProcessMemoryDumpAndCheckResponse(args.dump_guid); - - // Send a synthetic browser -> child global memory dump response. - SimulateSyntheticMessageFromBrowser( - TracingMsg_GlobalMemoryDumpResponse(args.dump_guid, true)); - - DisableTracing(); -} - -// Covers the case of a global memory dump being requested while another one is -// in progress and has not been acknowledged by the browser. The second request -// is expected to fail immediately, while the first one is expected to suceed. -TEST_F(ChildTracingTest, OverlappingChildInitiatedMemoryDumps) { - EnableTracingWithMemoryDumps(); - - // Expect that our mock dump provider is called only once. - EXPECT_CALL(*mock_dump_provider_, OnMemoryDump(_, _)) - .Times(1) - .WillRepeatedly(Return(true)); - - // Send the global memory dump request to the browser. - render_thread_->sink().ClearMessages(); - MemoryDumpManager::GetInstance()->RequestGlobalDump( - MemoryDumpType::EXPLICITLY_TRIGGERED, MemoryDumpLevelOfDetail::DETAILED, - callback_); - base::RunLoop().RunUntilIdle(); - - // Check that the child -> browser global dump request IPC is actually sent. - MemoryDumpRequestArgs args = GetInterceptedGlobalMemoryDumpRequest(); - EXPECT_EQ(MemoryDumpType::EXPLICITLY_TRIGGERED, args.dump_type); - - // Emulate a browser -> child process dump request and corresponding response. - RequestProcessMemoryDumpAndCheckResponse(args.dump_guid); - - // Before the response for the first global dump is sent, send another one, - // and expect that to fail. - render_thread_->sink().ClearMessages(); - MemoryDumpManager::GetInstance()->RequestGlobalDump( - MemoryDumpType::EXPLICITLY_TRIGGERED, MemoryDumpLevelOfDetail::DETAILED, - callback_); - base::RunLoop().RunUntilIdle(); - - EXPECT_EQ(1u, callback_call_count_); - EXPECT_FALSE(last_callback_status_); - // Whatever the guid of the second failing request is, it cannot possibly be - // equal to the guid of the first request. - EXPECT_NE(args.dump_guid, last_callback_dump_guid_); - - // Also, check that no request has been forwarded to the browser (because the - // first request is still outstanding and has not received any response yet). - EXPECT_EQ(nullptr, render_thread_->sink().GetUniqueMessageMatching( - TracingHostMsg_GlobalMemoryDumpRequest::ID)); - - // Now send a synthetic browser -> child response to the first request. - SimulateSyntheticMessageFromBrowser( - TracingMsg_GlobalMemoryDumpResponse(args.dump_guid, true)); - - // Verify that the the callback for the first request is finally called. - EXPECT_EQ(2u, callback_call_count_); - EXPECT_EQ(args.dump_guid, last_callback_dump_guid_); - EXPECT_TRUE(last_callback_status_); - - DisableTracing(); -} - -// Covers the case of five child-initiated global memory dumps. Each global dump -// request has a callback, which is expected to fail for 3 out of 5 cases. -TEST_F(ChildTracingTest, MultipleChildInitiatedMemoryDumpWithFailures) { - const uint32_t kNumRequests = 5; - MemoryDumpType kDumpType = MemoryDumpType::EXPLICITLY_TRIGGERED; - - EnableTracingWithMemoryDumps(); - EXPECT_CALL(*mock_dump_provider_, OnMemoryDump(_, _)) - .Times(kNumRequests) - .WillRepeatedly(Return(true)); - - for (uint32_t i = 0; i < kNumRequests; ++i) { - render_thread_->sink().ClearMessages(); - MemoryDumpManager::GetInstance()->RequestGlobalDump( - kDumpType, MemoryDumpLevelOfDetail::DETAILED, callback_); - base::RunLoop().RunUntilIdle(); - - MemoryDumpRequestArgs args = GetInterceptedGlobalMemoryDumpRequest(); - EXPECT_EQ(kDumpType, args.dump_type); - RequestProcessMemoryDumpAndCheckResponse(args.dump_guid); - - const bool success = (i & 1) ? true : false; - SimulateSyntheticMessageFromBrowser( - TracingMsg_GlobalMemoryDumpResponse(args.dump_guid, success)); - EXPECT_EQ(i + 1, callback_call_count_); - EXPECT_EQ(args.dump_guid, last_callback_dump_guid_); - EXPECT_EQ(success, last_callback_status_); - } - - DisableTracing(); -} - -} // namespace tracing diff --git a/chromium/components/tracing/common/process_metrics_memory_dump_provider.cc b/chromium/components/tracing/common/process_metrics_memory_dump_provider.cc index d8a29651182..2936256acd3 100644 --- a/chromium/components/tracing/common/process_metrics_memory_dump_provider.cc +++ b/chromium/components/tracing/common/process_metrics_memory_dump_provider.cc @@ -36,6 +36,7 @@ #include <mach/mach.h> #include "base/numerics/safe_math.h" +#include "base/process/process_metrics.h" #endif // defined(OS_MACOSX) #if defined(OS_WIN) @@ -387,31 +388,20 @@ bool GetDyldRegions(std::vector<VMRegion>* regions) { return true; } -void PopulateByteStats(VMRegion* region, const vm_region_submap_info_64& info) { - uint32_t share_mode = info.share_mode; - if (share_mode == SM_COW && info.ref_count == 1) - share_mode = SM_PRIVATE; - - uint64_t dirty_bytes = info.pages_dirtied * PAGE_SIZE; - uint64_t clean_bytes = - (info.pages_resident - info.pages_reusable - info.pages_dirtied) * - PAGE_SIZE; - switch (share_mode) { +void PopulateByteStats(VMRegion* region, + const vm_region_top_info_data_t& info) { + uint64_t dirty_bytes = + (info.private_pages_resident + info.shared_pages_resident) * PAGE_SIZE; + switch (info.share_mode) { case SM_LARGE_PAGE: case SM_PRIVATE: - region->byte_stats_private_dirty_resident = dirty_bytes; - region->byte_stats_private_clean_resident = clean_bytes; - break; case SM_COW: region->byte_stats_private_dirty_resident = dirty_bytes; - region->byte_stats_shared_clean_resident = clean_bytes; - break; case SM_SHARED: case SM_PRIVATE_ALIASED: case SM_TRUESHARED: case SM_SHARED_ALIASED: region->byte_stats_shared_dirty_resident = dirty_bytes; - region->byte_stats_shared_clean_resident = clean_bytes; break; case SM_EMPTY: break; @@ -421,38 +411,45 @@ void PopulateByteStats(VMRegion* region, const vm_region_submap_info_64& info) { } } -// Creates VMRegions from mach_vm_region_recurse. Returns whether the operation +// Creates VMRegions using mach vm syscalls. Returns whether the operation // succeeded. bool GetAllRegions(std::vector<VMRegion>* regions) { const int pid = getpid(); task_t task = mach_task_self(); mach_vm_size_t size = 0; - vm_region_submap_info_64 info; - natural_t depth = 1; - mach_msg_type_number_t count = sizeof(info); - for (mach_vm_address_t address = MACH_VM_MIN_ADDRESS;; address += size) { - memset(&info, 0, sizeof(info)); - kern_return_t kr = mach_vm_region_recurse( - task, &address, &size, &depth, - reinterpret_cast<vm_region_info_t>(&info), &count); - if (kr == KERN_INVALID_ADDRESS) // nothing else left + mach_vm_address_t address = MACH_VM_MIN_ADDRESS; + while (true) { + base::CheckedNumeric<mach_vm_address_t> next_address(address); + next_address += size; + if (!next_address.IsValid()) + return false; + address = next_address.ValueOrDie(); + mach_vm_address_t address_copy = address; + + vm_region_top_info_data_t info; + base::MachVMRegionResult result = + base::GetTopInfo(task, &size, &address, &info); + if (result == base::MachVMRegionResult::Error) + return false; + if (result == base::MachVMRegionResult::Finished) break; - if (kr != KERN_SUCCESS) // something bad + + vm_region_basic_info_64 basic_info; + mach_vm_size_t dummy_size = 0; + result = base::GetBasicInfo(task, &dummy_size, &address_copy, &basic_info); + if (result == base::MachVMRegionResult::Error) return false; - if (info.is_submap) { - size = 0; - ++depth; - continue; - } + if (result == base::MachVMRegionResult::Finished) + break; VMRegion region; PopulateByteStats(®ion, info); - if (info.protection & VM_PROT_READ) + if (basic_info.protection & VM_PROT_READ) region.protection_flags |= VMRegion::kProtectionFlagsRead; - if (info.protection & VM_PROT_WRITE) + if (basic_info.protection & VM_PROT_WRITE) region.protection_flags |= VMRegion::kProtectionFlagsWrite; - if (info.protection & VM_PROT_EXECUTE) + if (basic_info.protection & VM_PROT_EXECUTE) region.protection_flags |= VMRegion::kProtectionFlagsExec; char buffer[MAXPATHLEN]; @@ -460,16 +457,12 @@ bool GetAllRegions(std::vector<VMRegion>* regions) { if (length != 0) region.mapped_file.assign(buffer, length); - region.byte_stats_swapped = info.pages_swapped_out * PAGE_SIZE; + // There's no way to get swapped or clean bytes without doing a + // very expensive syscalls that crawls every single page in the memory + // object. region.start_address = address; region.size_in_bytes = size; regions->push_back(region); - - base::CheckedNumeric<mach_vm_address_t> numeric(address); - numeric += size; - if (!numeric.IsValid()) - return false; - address = numeric.ValueOrDie(); } return true; } @@ -608,9 +601,24 @@ bool ProcessMetricsMemoryDumpProvider::OnMemoryDump( bool ProcessMetricsMemoryDumpProvider::DumpProcessTotals( const base::trace_event::MemoryDumpArgs& args, base::trace_event::ProcessMemoryDump* pmd) { - const uint64_t rss_bytes = rss_bytes_for_testing - ? rss_bytes_for_testing - : process_metrics_->GetWorkingSetSize(); +#if defined(OS_MACOSX) + size_t private_bytes; + size_t shared_bytes; + size_t resident_bytes; + size_t locked_bytes; + if (!process_metrics_->GetMemoryBytes(&private_bytes, &shared_bytes, + &resident_bytes, &locked_bytes)) { + return false; + } + uint64_t rss_bytes = resident_bytes; + pmd->process_totals()->SetExtraFieldInBytes("private_bytes", private_bytes); + pmd->process_totals()->SetExtraFieldInBytes("shared_bytes", shared_bytes); + pmd->process_totals()->SetExtraFieldInBytes("locked_bytes", locked_bytes); +#else + uint64_t rss_bytes = process_metrics_->GetWorkingSetSize(); +#endif // defined(OS_MACOSX) + if (rss_bytes_for_testing) + rss_bytes = rss_bytes_for_testing; // rss_bytes will be 0 if the process ended while dumping. if (!rss_bytes) @@ -637,12 +645,6 @@ bool ProcessMetricsMemoryDumpProvider::DumpProcessTotals( } close(clear_refs_fd); } -#elif defined(MACOSX) - size_t private_bytes; - bool res = process_metrics_->GetMemoryBytes(&private_bytes, - nullptr /* shared_bytes */); - if (res) - pmd->process_totals()->SetExtraFieldInBytes("private_bytes", private_bytes); #elif defined(OS_WIN) if (args.level_of_detail == base::trace_event::MemoryDumpLevelOfDetail::DETAILED) { diff --git a/chromium/components/tracing/common/process_metrics_memory_dump_provider_unittest.cc b/chromium/components/tracing/common/process_metrics_memory_dump_provider_unittest.cc index 77124349694..b28d3f2aad6 100644 --- a/chromium/components/tracing/common/process_metrics_memory_dump_provider_unittest.cc +++ b/chromium/components/tracing/common/process_metrics_memory_dump_provider_unittest.cc @@ -410,28 +410,5 @@ TEST(ProcessMetricsMemoryDumpProviderTest, TestMachOReading) { EXPECT_TRUE(found_appkit); } -TEST(ProcessMetricsMemoryDumpProviderTest, NoDuplicateRegions) { - using VMRegion = base::trace_event::ProcessMemoryMaps::VMRegion; - ProcessMetricsMemoryDumpProvider mdp(base::kNullProcessId); - base::trace_event::MemoryDumpArgs args; - base::trace_event::ProcessMemoryDump dump(nullptr, args); - ASSERT_TRUE(mdp.DumpProcessMemoryMaps(args, &dump)); - ASSERT_TRUE(dump.has_process_mmaps()); - - std::vector<VMRegion> regions; - regions.reserve(dump.process_mmaps()->vm_regions().size()); - for (const VMRegion& region : dump.process_mmaps()->vm_regions()) - regions.push_back(region); - std::sort(regions.begin(), regions.end(), - [](const VMRegion& a, const VMRegion& b) -> bool { - return a.start_address < b.start_address; - }); - uint64_t last_address = 0; - for (const VMRegion& region : regions) { - EXPECT_GE(region.start_address, last_address); - last_address = region.start_address + region.size_in_bytes; - } -} - #endif // defined(OS_MACOSX) } // namespace tracing diff --git a/chromium/components/tracing/common/trace_startup.cc b/chromium/components/tracing/common/trace_startup.cc index 2c8ae37025c..551564c6709 100644 --- a/chromium/components/tracing/common/trace_startup.cc +++ b/chromium/components/tracing/common/trace_startup.cc @@ -38,10 +38,14 @@ void EnableStartupTracingIfNeeded(bool can_access_file_system) { trace_config, base::trace_event::TraceLog::RECORDING_MODE); } else if (can_access_file_system && tracing::TraceConfigFile::GetInstance()->IsEnabled()) { + const base::trace_event::TraceConfig& trace_config = + tracing::TraceConfigFile::GetInstance()->GetTraceConfig(); + uint8_t modes = base::trace_event::TraceLog::RECORDING_MODE; + if (!trace_config.event_filters().empty()) + modes |= base::trace_event::TraceLog::FILTERING_MODE; // This checks kTraceConfigFile switch. base::trace_event::TraceLog::GetInstance()->SetEnabled( - tracing::TraceConfigFile::GetInstance()->GetTraceConfig(), - base::trace_event::TraceLog::RECORDING_MODE); + tracing::TraceConfigFile::GetInstance()->GetTraceConfig(), modes); } } diff --git a/chromium/components/tracing/core/proto_zero_message.cc b/chromium/components/tracing/core/proto_zero_message.cc index a555683428c..20785476d13 100644 --- a/chromium/components/tracing/core/proto_zero_message.cc +++ b/chromium/components/tracing/core/proto_zero_message.cc @@ -24,7 +24,7 @@ ProtoZeroMessage::ProtoZeroMessage() { // |nested_messages_arena_| and implictly destroyed when the arena of the // root message goes away. This is fine as long as all the fields are PODs, // hence the static_assert below. - static_assert(base::is_trivially_destructible<ProtoZeroMessage>::value, + static_assert(std::is_trivially_destructible<ProtoZeroMessage>::value, "ProtoZeroMessage must be trivially destructible"); static_assert( diff --git a/chromium/components/tracing/tools/proto_zero_plugin/BUILD.gn b/chromium/components/tracing/tools/proto_zero_plugin/BUILD.gn index cdf0eb16073..15a71404391 100644 --- a/chromium/components/tracing/tools/proto_zero_plugin/BUILD.gn +++ b/chromium/components/tracing/tools/proto_zero_plugin/BUILD.gn @@ -12,5 +12,11 @@ if (current_toolchain == host_toolchain) { deps = [ "//third_party/protobuf:protoc_lib", ] + if (is_win) { + # TODO(thomasanderson): remove when https://crbug.com/703251 is resolved + # by Microsoft. + configs -= [ "//build/config/win:default_incremental_linking" ] + configs += [ "//build/config/win:no_incremental_linking" ] + } } } |