diff options
-rw-r--r-- | base/trace_event/trace_event_impl.cc | 40 | ||||
-rw-r--r-- | base/trace_event/trace_event_impl.h | 13 | ||||
-rw-r--r-- | base/trace_event/trace_event_unittest.cc | 26 | ||||
-rw-r--r-- | components/tracing/child_trace_message_filter.cc | 6 | ||||
-rw-r--r-- | components/tracing/child_trace_message_filter.h | 1 | ||||
-rw-r--r-- | components/tracing/tracing_messages.h | 3 | ||||
-rw-r--r-- | content/browser/tracing/trace_message_filter.cc | 7 | ||||
-rw-r--r-- | content/browser/tracing/trace_message_filter.h | 1 | ||||
-rw-r--r-- | content/browser/tracing/tracing_controller_impl.cc | 28 |
9 files changed, 106 insertions, 19 deletions
diff --git a/base/trace_event/trace_event_impl.cc b/base/trace_event/trace_event_impl.cc index 8051605..3925710 100644 --- a/base/trace_event/trace_event_impl.cc +++ b/base/trace_event/trace_event_impl.cc @@ -1769,6 +1769,17 @@ void TraceLog::SetEventCallbackDisabled() { // 4. If any thread hasn't finish its flush in time, finish the flush. void TraceLog::Flush(const TraceLog::OutputCallback& cb, bool use_worker_thread) { + FlushInternal(cb, use_worker_thread, false); +} + +void TraceLog::CancelTracing(const OutputCallback& cb) { + SetDisabled(); + FlushInternal(cb, false, true); +} + +void TraceLog::FlushInternal(const TraceLog::OutputCallback& cb, + bool use_worker_thread, + bool discard_events) { use_worker_thread_ = use_worker_thread; if (IsEnabled()) { // Can't flush when tracing is enabled because otherwise PostTask would @@ -1812,17 +1823,17 @@ void TraceLog::Flush(const TraceLog::OutputCallback& cb, if (thread_message_loop_task_runners.size()) { for (size_t i = 0; i < thread_message_loop_task_runners.size(); ++i) { thread_message_loop_task_runners[i]->PostTask( - FROM_HERE, - Bind(&TraceLog::FlushCurrentThread, Unretained(this), generation)); + FROM_HERE, Bind(&TraceLog::FlushCurrentThread, Unretained(this), + generation, discard_events)); } flush_task_runner_->PostDelayedTask( - FROM_HERE, - Bind(&TraceLog::OnFlushTimeout, Unretained(this), generation), + FROM_HERE, Bind(&TraceLog::OnFlushTimeout, Unretained(this), generation, + discard_events), TimeDelta::FromMilliseconds(kThreadFlushTimeoutMs)); return; } - FinishFlush(generation); + FinishFlush(generation, discard_events); } // Usually it runs on a different thread. @@ -1852,7 +1863,7 @@ void TraceLog::ConvertTraceEventsToTraceFormat( flush_output_callback.Run(json_events_str_ptr, false); } -void TraceLog::FinishFlush(int generation) { +void TraceLog::FinishFlush(int generation, bool discard_events) { scoped_ptr<TraceBuffer> previous_logged_events; OutputCallback flush_output_callback; TraceEvent::ArgumentFilterPredicate argument_filter_predicate; @@ -1877,6 +1888,14 @@ void TraceLog::FinishFlush(int generation) { } } + if (discard_events) { + if (!flush_output_callback.is_null()) { + scoped_refptr<RefCountedString> empty_result = new RefCountedString; + flush_output_callback.Run(empty_result, false); + } + return; + } + if (use_worker_thread_ && WorkerPool::PostTask( FROM_HERE, Bind(&TraceLog::ConvertTraceEventsToTraceFormat, @@ -1892,7 +1911,7 @@ void TraceLog::FinishFlush(int generation) { } // Run in each thread holding a local event buffer. -void TraceLog::FlushCurrentThread(int generation) { +void TraceLog::FlushCurrentThread(int generation, bool discard_events) { { AutoLock lock(lock_); if (!CheckGeneration(generation) || !flush_task_runner_) { @@ -1910,10 +1929,11 @@ void TraceLog::FlushCurrentThread(int generation) { return; flush_task_runner_->PostTask( - FROM_HERE, Bind(&TraceLog::FinishFlush, Unretained(this), generation)); + FROM_HERE, Bind(&TraceLog::FinishFlush, Unretained(this), generation, + discard_events)); } -void TraceLog::OnFlushTimeout(int generation) { +void TraceLog::OnFlushTimeout(int generation, bool discard_events) { { AutoLock lock(lock_); if (!CheckGeneration(generation) || !flush_task_runner_) { @@ -1932,7 +1952,7 @@ void TraceLog::OnFlushTimeout(int generation) { LOG(WARNING) << "Thread: " << (*it)->thread_name(); } } - FinishFlush(generation); + FinishFlush(generation, discard_events); } void TraceLog::FlushButLeaveBufferIntact( diff --git a/base/trace_event/trace_event_impl.h b/base/trace_event/trace_event_impl.h index 2922840..ccb8500 100644 --- a/base/trace_event/trace_event_impl.h +++ b/base/trace_event/trace_event_impl.h @@ -428,6 +428,9 @@ class BASE_EXPORT TraceLog : public MemoryDumpProvider { void Flush(const OutputCallback& cb, bool use_worker_thread = false); void FlushButLeaveBufferIntact(const OutputCallback& flush_output_callback); + // Cancels tracing and discards collected data. + void CancelTracing(const OutputCallback& cb); + // Called by TRACE_EVENT* macros, don't call this directly. // The name parameter is a category group for example: // TRACE_EVENT0("renderer,webkit", "WebViewImpl::HandleInputEvent") @@ -596,16 +599,20 @@ class BASE_EXPORT TraceLog : public MemoryDumpProvider { TraceEvent* GetEventByHandleInternal(TraceEventHandle handle, OptionalAutoLock* lock); + void FlushInternal(const OutputCallback& cb, + bool use_worker_thread, + bool discard_events); + // |generation| is used in the following callbacks to check if the callback // is called for the flush of the current |logged_events_|. - void FlushCurrentThread(int generation); + void FlushCurrentThread(int generation, bool discard_events); // Usually it runs on a different thread. static void ConvertTraceEventsToTraceFormat( scoped_ptr<TraceBuffer> logged_events, const TraceLog::OutputCallback& flush_output_callback, const TraceEvent::ArgumentFilterPredicate& argument_filter_predicate); - void FinishFlush(int generation); - void OnFlushTimeout(int generation); + void FinishFlush(int generation, bool discard_events); + void OnFlushTimeout(int generation, bool discard_events); int generation() const { return static_cast<int>(subtle::NoBarrier_Load(&generation_)); diff --git a/base/trace_event/trace_event_unittest.cc b/base/trace_event/trace_event_unittest.cc index 1827aa8..d648129 100644 --- a/base/trace_event/trace_event_unittest.cc +++ b/base/trace_event/trace_event_unittest.cc @@ -87,6 +87,12 @@ class TraceEventTestFixture : public testing::Test { TraceLog::RECORDING_MODE); } + void CancelTrace() { + WaitableEvent flush_complete_event(false, false); + CancelTraceAsync(&flush_complete_event); + flush_complete_event.Wait(); + } + void EndTraceAndFlush() { num_flush_callbacks_ = 0; WaitableEvent flush_complete_event(false, false); @@ -106,6 +112,13 @@ class TraceEventTestFixture : public testing::Test { flush_complete_event.Wait(); } + void CancelTraceAsync(WaitableEvent* flush_complete_event) { + TraceLog::GetInstance()->CancelTracing( + base::Bind(&TraceEventTestFixture::OnTraceDataCollected, + base::Unretained(static_cast<TraceEventTestFixture*>(this)), + base::Unretained(flush_complete_event))); + } + void EndTraceAndFlushAsync(WaitableEvent* flush_complete_event) { TraceLog::GetInstance()->SetDisabled(); TraceLog::GetInstance()->Flush( @@ -908,6 +921,19 @@ TEST_F(TraceEventTestFixture, DataCaptured) { ValidateAllTraceMacrosCreatedData(trace_parsed_); } +// Emit some events and validate that only empty strings are received +// if we tell Flush() to discard events. +TEST_F(TraceEventTestFixture, DataDiscarded) { + TraceLog::GetInstance()->SetEnabled(TraceConfig(kRecordAllCategoryFilter, ""), + TraceLog::RECORDING_MODE); + + TraceWithAllMacroVariants(NULL); + + CancelTrace(); + + EXPECT_TRUE(trace_parsed_.empty()); +} + class MockEnabledStateChangedObserver : public TraceLog::EnabledStateObserver { public: diff --git a/components/tracing/child_trace_message_filter.cc b/components/tracing/child_trace_message_filter.cc index ad34a24..b3babc2 100644 --- a/components/tracing/child_trace_message_filter.cc +++ b/components/tracing/child_trace_message_filter.cc @@ -38,6 +38,7 @@ bool ChildTraceMessageFilter::OnMessageReceived(const IPC::Message& message) { IPC_BEGIN_MESSAGE_MAP(ChildTraceMessageFilter, message) IPC_MESSAGE_HANDLER(TracingMsg_BeginTracing, OnBeginTracing) IPC_MESSAGE_HANDLER(TracingMsg_EndTracing, OnEndTracing) + IPC_MESSAGE_HANDLER(TracingMsg_CancelTracing, OnCancelTracing) IPC_MESSAGE_HANDLER(TracingMsg_EnableMonitoring, OnEnableMonitoring) IPC_MESSAGE_HANDLER(TracingMsg_DisableMonitoring, OnDisableMonitoring) IPC_MESSAGE_HANDLER(TracingMsg_CaptureMonitoringSnapshot, @@ -82,6 +83,11 @@ void ChildTraceMessageFilter::OnEndTracing() { base::Bind(&ChildTraceMessageFilter::OnTraceDataCollected, this)); } +void ChildTraceMessageFilter::OnCancelTracing() { + TraceLog::GetInstance()->CancelTracing( + base::Bind(&ChildTraceMessageFilter::OnTraceDataCollected, this)); +} + void ChildTraceMessageFilter::OnEnableMonitoring( const std::string& trace_config_str, base::TraceTicks browser_time) { diff --git a/components/tracing/child_trace_message_filter.h b/components/tracing/child_trace_message_filter.h index 494d25d..a075edb 100644 --- a/components/tracing/child_trace_message_filter.h +++ b/components/tracing/child_trace_message_filter.h @@ -43,6 +43,7 @@ class ChildTraceMessageFilter : public IPC::MessageFilter { void OnBeginTracing(const std::string& trace_config_str, base::TraceTicks browser_time); void OnEndTracing(); + void OnCancelTracing(); void OnEnableMonitoring(const std::string& trace_config_str, base::TraceTicks browser_time); void OnDisableMonitoring(); diff --git a/components/tracing/tracing_messages.h b/components/tracing/tracing_messages.h index 14f31bb..ebdefc1 100644 --- a/components/tracing/tracing_messages.h +++ b/components/tracing/tracing_messages.h @@ -39,6 +39,9 @@ IPC_MESSAGE_CONTROL2(TracingMsg_BeginTracing, // Sent to all child processes to disable trace event recording. IPC_MESSAGE_CONTROL0(TracingMsg_EndTracing) +// Sent to all child processes to cancel trace event recording. +IPC_MESSAGE_CONTROL0(TracingMsg_CancelTracing) + // Sent to all child processes to start monitoring. IPC_MESSAGE_CONTROL2(TracingMsg_EnableMonitoring, std::string /* trace_config_str */, diff --git a/content/browser/tracing/trace_message_filter.cc b/content/browser/tracing/trace_message_filter.cc index 1ded8e5..6d48523 100644 --- a/content/browser/tracing/trace_message_filter.cc +++ b/content/browser/tracing/trace_message_filter.cc @@ -74,6 +74,13 @@ void TraceMessageFilter::SendEndTracing() { Send(new TracingMsg_EndTracing); } +void TraceMessageFilter::SendCancelTracing() { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + DCHECK(!is_awaiting_end_ack_); + is_awaiting_end_ack_ = true; + Send(new TracingMsg_CancelTracing); +} + void TraceMessageFilter::SendEnableMonitoring( const base::trace_event::TraceConfig& trace_config) { DCHECK_CURRENTLY_ON(BrowserThread::UI); diff --git a/content/browser/tracing/trace_message_filter.h b/content/browser/tracing/trace_message_filter.h index 0d1f05c..3bc7ccc 100644 --- a/content/browser/tracing/trace_message_filter.h +++ b/content/browser/tracing/trace_message_filter.h @@ -28,6 +28,7 @@ class TraceMessageFilter : public BrowserMessageFilter { void SendBeginTracing( const base::trace_event::TraceConfig& trace_config); void SendEndTracing(); + void SendCancelTracing(); void SendEnableMonitoring( const base::trace_event::TraceConfig& trace_config); void SendDisableMonitoring(); diff --git a/content/browser/tracing/tracing_controller_impl.cc b/content/browser/tracing/tracing_controller_impl.cc index 5c94a0b..ce9b854 100644 --- a/content/browser/tracing/tracing_controller_impl.cc +++ b/content/browser/tracing/tracing_controller_impl.cc @@ -231,17 +231,27 @@ void TracingControllerImpl::OnDisableRecordingDone() { // trace log. Once the flush has completed the caller will be notified that // tracing has ended. if (pending_disable_recording_ack_count_ == 1) { - // Flush asynchronously now, because we don't have any children to wait for. - TraceLog::GetInstance()->Flush( - base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected, - base::Unretained(this)), - true); + // Flush/cancel asynchronously now, because we don't have any children to + // wait for. + if (trace_data_sink_) { + TraceLog::GetInstance()->Flush( + base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected, + base::Unretained(this)), + true); + } else { + TraceLog::GetInstance()->CancelTracing( + base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected, + base::Unretained(this))); + } } // Notify all child processes. for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin(); it != trace_message_filters_.end(); ++it) { - it->get()->SendEndTracing(); + if (trace_data_sink_) + it->get()->SendEndTracing(); + else + it->get()->SendCancelTracing(); } } @@ -566,10 +576,16 @@ void TracingControllerImpl::OnDisableRecordingAcked( // All acks from subprocesses have been received. Now flush the local trace. // During or after this call, our OnLocalTraceDataCollected will be // called with the last of the local trace data. + if (trace_data_sink_) { TraceLog::GetInstance()->Flush( base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected, base::Unretained(this)), true); + } else { + TraceLog::GetInstance()->CancelTracing( + base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected, + base::Unretained(this))); + } return; } |