From cdb35ad47ad00fcf958ff4c9ac312021b0a7c0a5 Mon Sep 17 00:00:00 2001 From: primiano Date: Mon, 13 Apr 2015 12:49:00 -0700 Subject: [PATCH] [tracing] browser-process-side impl for inter-process memory dumps This CL introduces the implementation for handling the inter-process memory dumps on the browser-process side. The browser process' MemoryDumpManager is in charge to coordinate the global dumps across all processes. Concretely this happens in the TracingControllerImpl (which already does some similar coordinations for other inter-process tracing tasks). In practice the coordiantion consists of: 1. Firing off one LocalMemoryDump request IPC per child process, or NACK-ing the request if another global dump is in progress. 2. Wait for child processes' ACK/NACKs 3a. Invoking the global memory dump callback when all the responses are received (if the dump was initiated by the browser process). 3b. Send a GlobalMemoryDump response IPC to the child process that initiated the global dump (if initiated by child-process). Plus all the necessary bookkeeping data structures. More context and design doc are available in the attached BUG. BUG=462930 Review URL: https://codereview.chromium.org/1039963004 Cr-Commit-Position: refs/heads/master@{#324902} --- content/browser/tracing/tracing_controller_impl.cc | 74 ++++++++++++++++++---- content/browser/tracing/tracing_controller_impl.h | 8 +++ 2 files changed, 71 insertions(+), 11 deletions(-) diff --git a/content/browser/tracing/tracing_controller_impl.cc b/content/browser/tracing/tracing_controller_impl.cc index 869946fb5106..55cdbc71b56c 100644 --- a/content/browser/tracing/tracing_controller_impl.cc +++ b/content/browser/tracing/tracing_controller_impl.cc @@ -168,6 +168,7 @@ TracingControllerImpl::TracingControllerImpl() pending_trace_log_status_ack_count_(0), maximum_trace_buffer_usage_(0), approximate_event_count_(0), + failed_memory_dump_count_(0), // Tracing may have been enabled by ContentMainRunner if kTraceStartup // is specified in command line. #if defined(OS_CHROMEOS) || defined(OS_WIN) @@ -649,7 +650,16 @@ void TracingControllerImpl::RemoveTraceMessageFilter( base::trace_event::TraceLogStatus())); } } - + TraceMessageFilterSet::const_iterator it = + pending_memory_dump_filters_.find(trace_message_filter); + if (it != pending_memory_dump_filters_.end()) { + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind(&TracingControllerImpl::OnProcessMemoryDumpResponse, + base::Unretained(this), + make_scoped_refptr(trace_message_filter), + pending_memory_dump_guid_, false /* success */)); + } trace_message_filters_.erase(trace_message_filter); } @@ -890,11 +900,34 @@ void TracingControllerImpl::RequestGlobalMemoryDump( base::Unretained(this), args, callback)); return; } - // TODO(primiano): send a local dump request to each of the child processes - // and do the bookkeeping to keep track of the outstanding requests. - // Also, at this point, this should check for collisions and bail out if a - // global dump is requested while another is already in progress. - NOTIMPLEMENTED(); + // Abort if another dump is already in progress. + if (pending_memory_dump_guid_) { + DVLOG(1) << "Requested memory dump " << args.dump_guid + << " while waiting for " << pending_memory_dump_guid_; + if (!callback.is_null()) + callback.Run(args.dump_guid, false /* success */); + return; + } + + pending_memory_dump_filters_.clear(); + failed_memory_dump_count_ = 0; + + base::trace_event::MemoryDumpManager::GetInstance()->CreateProcessDump(args); + + // If there are no child processes we are just done. + TraceMessageFilterSet::iterator it = trace_message_filters_.begin(); + if (it == trace_message_filters_.end()) { + if (!callback.is_null()) + callback.Run(args.dump_guid, true /* success */); + return; + } + + pending_memory_dump_guid_ = args.dump_guid; + pending_memory_dump_callback_ = callback; + pending_memory_dump_filters_ = trace_message_filters_; + + for (; it != trace_message_filters_.end(); ++it) + it->get()->SendProcessMemoryDumpRequest(args); } void TracingControllerImpl::OnProcessMemoryDumpResponse( @@ -910,11 +943,30 @@ void TracingControllerImpl::OnProcessMemoryDumpResponse( success)); return; } - // TODO(primiano): update the bookkeeping structs and, if this was the - // response from the last pending child, fire the completion callback, which - // in turn will cause a GlobalMemoryDumpResponse message to be sent back to - // the child, if this global dump was NOT initiated by the browser. - NOTIMPLEMENTED(); + + TraceMessageFilterSet::iterator it = + pending_memory_dump_filters_.find(trace_message_filter); + + if (pending_memory_dump_guid_ != dump_guid || + it == pending_memory_dump_filters_.end()) { + DLOG(WARNING) << "Received unexpected memory dump response: " << dump_guid; + return; + } + + if (!success) + failed_memory_dump_count_++; + + pending_memory_dump_filters_.erase(it); + + if (pending_memory_dump_filters_.empty()) { + // Got response from all child proceses. + if (!pending_memory_dump_callback_.is_null()) { + const bool global_success = failed_memory_dump_count_ == 0; + pending_memory_dump_callback_.Run(dump_guid, global_success); + pending_memory_dump_callback_ = base::trace_event::MemoryDumpCallback(); + } + pending_memory_dump_guid_ = 0; + } } void TracingControllerImpl::OnMonitoringStateChanged(bool is_monitoring) { diff --git a/content/browser/tracing/tracing_controller_impl.h b/content/browser/tracing/tracing_controller_impl.h index d22402cdafec..d62b5141bcab 100644 --- a/content/browser/tracing/tracing_controller_impl.h +++ b/content/browser/tracing/tracing_controller_impl.h @@ -156,15 +156,23 @@ class TracingControllerImpl // Pending acks for DisableRecording. int pending_disable_recording_ack_count_; TraceMessageFilterSet pending_disable_recording_filters_; + // Pending acks for CaptureMonitoringSnapshot. int pending_capture_monitoring_snapshot_ack_count_; TraceMessageFilterSet pending_capture_monitoring_filters_; + // Pending acks for GetTraceLogStatus. int pending_trace_log_status_ack_count_; TraceMessageFilterSet pending_trace_log_status_filters_; float maximum_trace_buffer_usage_; size_t approximate_event_count_; + // Pending acks for memory RequestGlobalDumpPoint. + int failed_memory_dump_count_; + TraceMessageFilterSet pending_memory_dump_filters_; + uint64 pending_memory_dump_guid_; + base::trace_event::MemoryDumpCallback pending_memory_dump_callback_; + #if defined(OS_CHROMEOS) || defined(OS_WIN) bool is_system_tracing_; #endif -- 2.11.4.GIT