Index: trace_message_filter.cc =================================================================== --- trace_message_filter.cc (revision 247552) +++ trace_message_filter.cc (working copy) @@ -121,7 +121,7 @@ if (is_awaiting_end_ack_) { is_awaiting_end_ack_ = false; TracingControllerImpl::GetInstance()->OnDisableRecordingAcked( - known_categories); + this, known_categories); } else { NOTREACHED(); } @@ -132,7 +132,8 @@ // but check in case the child process is compromised. if (is_awaiting_capture_monitoring_snapshot_ack_) { is_awaiting_capture_monitoring_snapshot_ack_ = false; - TracingControllerImpl::GetInstance()->OnCaptureMonitoringSnapshotAcked(); + TracingControllerImpl::GetInstance()->OnCaptureMonitoringSnapshotAcked( + this); } else { NOTREACHED(); } @@ -160,7 +161,7 @@ if (is_awaiting_buffer_percent_full_ack_) { is_awaiting_buffer_percent_full_ack_ = false; TracingControllerImpl::GetInstance()->OnTraceBufferPercentFullReply( - percent_full); + this, percent_full); } else { NOTREACHED(); } Index: tracing_controller_impl.cc =================================================================== --- tracing_controller_impl.cc (revision 247552) +++ tracing_controller_impl.cc (working copy) @@ -177,7 +177,7 @@ is_recording_ = true; // Notify all child processes. - for (TraceMessageFilterMap::iterator it = trace_message_filters_.begin(); + for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin(); it != trace_message_filters_.end(); ++it) { it->get()->SendBeginTracing(category_filter, trace_options); } @@ -212,21 +212,20 @@ // Count myself (local trace) in pending_disable_recording_ack_count_, // acked below. pending_disable_recording_ack_count_ = trace_message_filters_.size() + 1; + pending_disable_recording_filters_ = trace_message_filters_; - // Handle special case of zero child processes by immediately telling the - // caller that tracing has ended. Use asynchronous OnDisableRecordingAcked - // to avoid recursive call back to the caller. + // Handle special case of zero child processes by immediately flushing the + // trace log. Once the flush has completed the caller will be notified that + // tracing has ended. if (pending_disable_recording_ack_count_ == 1) { - // Ack asynchronously now, because we don't have any children to wait for. - std::vector category_groups; - TraceLog::GetInstance()->GetKnownCategoryGroups(&category_groups); - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - base::Bind(&TracingControllerImpl::OnDisableRecordingAcked, - base::Unretained(this), category_groups)); + // Flush asynchronously now, because we don't have any children to wait for. + TraceLog::GetInstance()->Flush( + base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected, + base::Unretained(this))); } // Notify all child processes. - for (TraceMessageFilterMap::iterator it = trace_message_filters_.begin(); + for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin(); it != trace_message_filters_.end(); ++it) { it->get()->SendEndTracing(); } @@ -256,7 +255,7 @@ static_cast(monitoring_tracing_options)); // Notify all child processes. - for (TraceMessageFilterMap::iterator it = trace_message_filters_.begin(); + for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin(); it != trace_message_filters_.end(); ++it) { it->get()->SendEnableMonitoring(category_filter, static_cast(monitoring_tracing_options)); @@ -278,7 +277,7 @@ TraceLog::GetInstance()->SetDisabled(); // Notify all child processes. - for (TraceMessageFilterMap::iterator it = trace_message_filters_.begin(); + for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin(); it != trace_message_filters_.end(); ++it) { it->get()->SendDisableMonitoring(); } @@ -313,20 +312,20 @@ // acked below. pending_capture_monitoring_snapshot_ack_count_ = trace_message_filters_.size() + 1; + pending_capture_monitoring_filters_ = trace_message_filters_; - // Handle special case of zero child processes by immediately telling the - // caller that capturing snapshot has ended. Use asynchronous - // OnCaptureMonitoringSnapshotAcked to avoid recursive call back to the - // caller. + // Handle special case of zero child processes by immediately flushing the + // trace log. Once the flush has completed the caller will be notified that + // the capture snapshot has ended. if (pending_capture_monitoring_snapshot_ack_count_ == 1) { - // Ack asynchronously now, because we don't have any children to wait for. - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - base::Bind(&TracingControllerImpl::OnCaptureMonitoringSnapshotAcked, + // Flush asynchronously now, because we don't have any children to wait for. + TraceLog::GetInstance()->FlushButLeaveBufferIntact( + base::Bind(&TracingControllerImpl::OnLocalMonitoringTraceDataCollected, base::Unretained(this))); } // Notify all child processes. - for (TraceMessageFilterMap::iterator it = trace_message_filters_.begin(); + for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin(); it != trace_message_filters_.end(); ++it) { it->get()->SendCaptureMonitoringSnapshot(); } @@ -350,18 +349,20 @@ // Count myself in pending_trace_buffer_percent_full_ack_count_, acked below. pending_trace_buffer_percent_full_ack_count_ = trace_message_filters_.size() + 1; + pending_trace_buffer_percent_full_filters_ = trace_message_filters_; maximum_trace_buffer_percent_full_ = 0; - // Handle special case of zero child processes. - if (pending_trace_buffer_percent_full_ack_count_ == 1) { - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - base::Bind(&TracingControllerImpl::OnTraceBufferPercentFullReply, - base::Unretained(this), - TraceLog::GetInstance()->GetBufferPercentFull())); - } + // Call OnTraceBufferPercentFullReply unconditionally for the browser process. + // This will result in immediate execution of the callback if there are no + // child processes. + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, + base::Bind(&TracingControllerImpl::OnTraceBufferPercentFullReply, + base::Unretained(this), + scoped_refptr(), + TraceLog::GetInstance()->GetBufferPercentFull())); // Notify all child processes. - for (TraceMessageFilterMap::iterator it = trace_message_filters_.begin(); + for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin(); it != trace_message_filters_.end(); ++it) { it->get()->SendGetTraceBufferPercentFull(); } @@ -386,7 +387,7 @@ base::Bind(&TracingControllerImpl::OnWatchEventMatched, base::Unretained(this))); - for (TraceMessageFilterMap::iterator it = trace_message_filters_.begin(); + for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin(); it != trace_message_filters_.end(); ++it) { it->get()->SendSetWatchEvent(category_name, event_name); } @@ -399,7 +400,7 @@ if (!can_cancel_watch_event()) return false; - for (TraceMessageFilterMap::iterator it = trace_message_filters_.begin(); + for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin(); it != trace_message_filters_.end(); ++it) { it->get()->SendCancelWatchEvent(); } @@ -440,15 +441,54 @@ return; } + // If a filter is removed while a response from that filter is pending then + // simulate the response. Otherwise the response count will be wrong and the + // completion callback will never be executed. + if (pending_disable_recording_ack_count_ > 0) { + TraceMessageFilterSet::const_iterator it = + pending_disable_recording_filters_.find(trace_message_filter); + if (it != pending_disable_recording_filters_.end()) { + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, + base::Bind(&TracingControllerImpl::OnDisableRecordingAcked, + base::Unretained(this), + make_scoped_refptr(trace_message_filter), + std::vector())); + } + } + if (pending_capture_monitoring_snapshot_ack_count_ > 0) { + TraceMessageFilterSet::const_iterator it = + pending_capture_monitoring_filters_.find(trace_message_filter); + if (it != pending_capture_monitoring_filters_.end()) { + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, + base::Bind(&TracingControllerImpl::OnCaptureMonitoringSnapshotAcked, + base::Unretained(this), + make_scoped_refptr(trace_message_filter))); + } + } + if (pending_trace_buffer_percent_full_ack_count_ > 0) { + TraceMessageFilterSet::const_iterator it = + pending_trace_buffer_percent_full_filters_.find(trace_message_filter); + if (it != pending_trace_buffer_percent_full_filters_.end()) { + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, + base::Bind(&TracingControllerImpl::OnTraceBufferPercentFullReply, + base::Unretained(this), + make_scoped_refptr(trace_message_filter), + 0)); + } + } + trace_message_filters_.erase(trace_message_filter); } void TracingControllerImpl::OnDisableRecordingAcked( + TraceMessageFilter* trace_message_filter, const std::vector& known_category_groups) { if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(&TracingControllerImpl::OnDisableRecordingAcked, - base::Unretained(this), known_category_groups)); + base::Unretained(this), + make_scoped_refptr(trace_message_filter), + known_category_groups)); return; } @@ -459,6 +499,12 @@ if (pending_disable_recording_ack_count_ == 0) return; + if (trace_message_filter && + !pending_disable_recording_filters_.erase(trace_message_filter)) { + // The response from the specified message filter has already been received. + return; + } + if (--pending_disable_recording_ack_count_ == 1) { // All acks from subprocesses have been received. Now flush the local trace. // During or after this call, our OnLocalTraceDataCollected will be @@ -500,17 +546,25 @@ result_file_.reset(); } -void TracingControllerImpl::OnCaptureMonitoringSnapshotAcked() { +void TracingControllerImpl::OnCaptureMonitoringSnapshotAcked( + TraceMessageFilter* trace_message_filter) { if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(&TracingControllerImpl::OnCaptureMonitoringSnapshotAcked, - base::Unretained(this))); + base::Unretained(this), + make_scoped_refptr(trace_message_filter))); return; } if (pending_capture_monitoring_snapshot_ack_count_ == 0) return; + if (trace_message_filter && + !pending_capture_monitoring_filters_.erase(trace_message_filter)) { + // The response from the specified message filter has already been received. + return; + } + if (--pending_capture_monitoring_snapshot_ack_count_ == 1) { // All acks from subprocesses have been received. Now flush the local trace. // During or after this call, our OnLocalMonitoringTraceDataCollected @@ -585,7 +639,7 @@ // Simulate an DisableRecordingAcked for the local trace. std::vector category_groups; TraceLog::GetInstance()->GetKnownCategoryGroups(&category_groups); - OnDisableRecordingAcked(category_groups); + OnDisableRecordingAcked(NULL, category_groups); } void TracingControllerImpl::OnLocalMonitoringTraceDataCollected( @@ -598,20 +652,30 @@ return; // Simulate an CaptureMonitoringSnapshotAcked for the local trace. - OnCaptureMonitoringSnapshotAcked(); + OnCaptureMonitoringSnapshotAcked(NULL); } -void TracingControllerImpl::OnTraceBufferPercentFullReply(float percent_full) { +void TracingControllerImpl::OnTraceBufferPercentFullReply( + TraceMessageFilter* trace_message_filter, + float percent_full) { if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(&TracingControllerImpl::OnTraceBufferPercentFullReply, - base::Unretained(this), percent_full)); + base::Unretained(this), + make_scoped_refptr(trace_message_filter), + percent_full)); return; } if (pending_trace_buffer_percent_full_ack_count_ == 0) return; + if (trace_message_filter && + !pending_trace_buffer_percent_full_filters_.erase(trace_message_filter)) { + // The response from the specified message filter has already been received. + return; + } + maximum_trace_buffer_percent_full_ = std::max(maximum_trace_buffer_percent_full_, percent_full); @@ -621,15 +685,6 @@ maximum_trace_buffer_percent_full_); pending_trace_buffer_percent_full_callback_.Reset(); } - - if (pending_trace_buffer_percent_full_ack_count_ == 1) { - // The last ack represents local trace, so we need to ack it now. Note that - // this code only executes if there were child processes. - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - base::Bind(&TracingControllerImpl::OnTraceBufferPercentFullReply, - base::Unretained(this), - TraceLog::GetInstance()->GetBufferPercentFull())); - } } void TracingControllerImpl::OnWatchEventMatched() { Index: tracing_controller_impl.h =================================================================== --- tracing_controller_impl.h (revision 247552) +++ tracing_controller_impl.h (working copy) @@ -55,7 +55,7 @@ virtual bool CancelWatchEvent() OVERRIDE; private: - typedef std::set > TraceMessageFilterMap; + typedef std::set > TraceMessageFilterSet; class ResultFile; friend struct base::DefaultLazyInstanceTraits; @@ -107,23 +107,30 @@ bool has_more_events); void OnDisableRecordingAcked( + TraceMessageFilter* trace_message_filter, const std::vector& known_category_groups); void OnResultFileClosed(); - void OnCaptureMonitoringSnapshotAcked(); + void OnCaptureMonitoringSnapshotAcked( + TraceMessageFilter* trace_message_filter); void OnMonitoringSnapshotFileClosed(); - void OnTraceBufferPercentFullReply(float percent_full); + void OnTraceBufferPercentFullReply( + TraceMessageFilter* trace_message_filter, + float percent_full); void OnWatchEventMatched(); - TraceMessageFilterMap trace_message_filters_; + TraceMessageFilterSet trace_message_filters_; // 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 GetTraceBufferPercentFull. int pending_trace_buffer_percent_full_ack_count_; + TraceMessageFilterSet pending_trace_buffer_percent_full_filters_; float maximum_trace_buffer_percent_full_; bool is_recording_;