Index: trace_message_filter.cc =================================================================== --- trace_message_filter.cc (revision 241258) +++ 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 241258) +++ 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,6 +212,7 @@ // 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 flushing the // trace log. Once the flush has completed the caller will be notified that @@ -224,7 +225,7 @@ } // 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(); } @@ -254,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)); @@ -276,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(); } @@ -311,6 +312,7 @@ // 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 flushing the // trace log. Once the flush has completed the caller will be notified that @@ -323,7 +325,7 @@ } // 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(); } @@ -347,6 +349,7 @@ // 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. @@ -354,11 +357,12 @@ 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(); } @@ -383,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); } @@ -396,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(); } @@ -437,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; } @@ -456,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 @@ -497,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 @@ -582,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( @@ -595,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); @@ -625,6 +692,7 @@ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(&TracingControllerImpl::OnTraceBufferPercentFullReply, base::Unretained(this), + make_scoped_refptr(trace_message_filter), TraceLog::GetInstance()->GetBufferPercentFull())); } } Index: tracing_controller_impl.h =================================================================== --- tracing_controller_impl.h (revision 241258) +++ 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_;