ResetIncrState before all other track_event packets
While adding support for timestamp delta encoding, we realised that
first packet coming from track_event data source could be something
different from `ResetIncrementalState`. Which can cause problems.
For example, see line 87 in https://www.diffchecker.com/gKUL1x4J
As we are dropping the explicit `timestamp_clock_id` field from each
packet and utilising it's value from `trace_packet_defaults`, it's very
important to ensure that a packet which sets correct default values in
`trace_packet_defaults` comes before any other packets.
Bug: 224246750
Change-Id: I7790742052367c0a5828727857ec04a3b3b6bb0c
diff --git a/include/perfetto/tracing/internal/track_event_data_source.h b/include/perfetto/tracing/internal/track_event_data_source.h
index 2361352..633f3e2 100644
--- a/include/perfetto/tracing/internal/track_event_data_source.h
+++ b/include/perfetto/tracing/internal/track_event_data_source.h
@@ -361,7 +361,7 @@
TrackRegistry::Get()->UpdateTrack(track, desc.SerializeAsString());
Base::template Trace([&](typename Base::TraceContext ctx) {
TrackEventInternal::WriteTrackDescriptor(
- track, ctx.tls_inst_->trace_writer.get());
+ track, ctx.tls_inst_->trace_writer.get(), ctx.GetIncrementalState());
});
}
@@ -453,11 +453,8 @@
// Make sure incremental state is valid.
TraceWriterBase* trace_writer = ctx.tls_inst_->trace_writer.get();
TrackEventIncrementalState* incr_state = ctx.GetIncrementalState();
- if (incr_state->was_cleared) {
- incr_state->was_cleared = false;
- TrackEventInternal::ResetIncrementalState(trace_writer,
- trace_timestamp);
- }
+ TrackEventInternal::ResetIncrementalStateIfRequired(
+ trace_writer, incr_state, trace_timestamp);
// Write the track descriptor before any event on the track.
if (track) {
@@ -516,7 +513,7 @@
TrackRegistry::Get()->UpdateTrack(track, std::move(callback));
Base::template Trace([&](typename Base::TraceContext ctx) {
TrackEventInternal::WriteTrackDescriptor(
- track, ctx.tls_inst_->trace_writer.get());
+ track, ctx.tls_inst_->trace_writer.get(), ctx.GetIncrementalState());
});
}
diff --git a/include/perfetto/tracing/internal/track_event_internal.h b/include/perfetto/tracing/internal/track_event_internal.h
index 5bb6ec2..538274c 100644
--- a/include/perfetto/tracing/internal/track_event_internal.h
+++ b/include/perfetto/tracing/internal/track_event_internal.h
@@ -160,8 +160,15 @@
perfetto::protos::pbzero::TrackEvent::Type,
TraceTimestamp timestamp = {GetClockId(), GetTimeNs()});
- static void ResetIncrementalState(TraceWriterBase*, TraceTimestamp);
-
+ static void ResetIncrementalStateIfRequired(
+ TraceWriterBase* trace_writer,
+ TrackEventIncrementalState* incr_state,
+ TraceTimestamp timestamp) {
+ if (incr_state->was_cleared) {
+ incr_state->was_cleared = false;
+ ResetIncrementalState(trace_writer, incr_state, timestamp);
+ }
+ }
// TODO(altimin): Remove this method once Chrome uses
// EventContext::AddDebugAnnotation directly.
template <typename T>
@@ -184,15 +191,18 @@
auto it_and_inserted = incr_state->seen_tracks.insert(track.uuid);
if (PERFETTO_LIKELY(!it_and_inserted.second))
return;
- WriteTrackDescriptor(track, trace_writer);
+ WriteTrackDescriptor(track, trace_writer, incr_state);
}
// Unconditionally write a track descriptor into the trace.
template <typename TrackType>
static void WriteTrackDescriptor(const TrackType& track,
- TraceWriterBase* trace_writer) {
- TrackRegistry::Get()->SerializeTrack(
- track, NewTracePacket(trace_writer, {GetClockId(), GetTimeNs()}));
+ TraceWriterBase* trace_writer,
+ TrackEventIncrementalState* incr_state) {
+ TraceTimestamp ts = {GetClockId(), GetTimeNs()};
+ ResetIncrementalStateIfRequired(trace_writer, incr_state, ts);
+ TrackRegistry::Get()->SerializeTrack(track,
+ NewTracePacket(trace_writer, ts));
}
// Get the current time in nanoseconds in the trace clock timebase.
@@ -214,6 +224,10 @@
static const Track kDefaultTrack;
private:
+ static void ResetIncrementalState(TraceWriterBase*,
+ TrackEventIncrementalState* incr_state,
+ TraceTimestamp);
+
static protozero::MessageHandle<protos::pbzero::TracePacket> NewTracePacket(
TraceWriterBase*,
TraceTimestamp,
diff --git a/src/tracing/internal/track_event_internal.cc b/src/tracing/internal/track_event_internal.cc
index 3717fb2..c439c54 100644
--- a/src/tracing/internal/track_event_internal.cc
+++ b/src/tracing/internal/track_event_internal.cc
@@ -308,8 +308,10 @@
}
// static
-void TrackEventInternal::ResetIncrementalState(TraceWriterBase* trace_writer,
- TraceTimestamp timestamp) {
+void TrackEventInternal::ResetIncrementalState(
+ TraceWriterBase* trace_writer,
+ TrackEventIncrementalState* incr_state,
+ TraceTimestamp timestamp) {
auto default_track = ThreadTrack::Current();
{
// Mark any incremental state before this point invalid. Also set up
@@ -329,8 +331,8 @@
// trace points won't explicitly reference it. We also write the process
// descriptor from every thread that writes trace events to ensure it gets
// emitted at least once.
- WriteTrackDescriptor(default_track, trace_writer);
- WriteTrackDescriptor(ProcessTrack::Current(), trace_writer);
+ WriteTrackDescriptor(default_track, trace_writer, incr_state);
+ WriteTrackDescriptor(ProcessTrack::Current(), trace_writer, incr_state);
}
// static
diff --git a/src/tracing/test/api_integrationtest.cc b/src/tracing/test/api_integrationtest.cc
index 26d8a03..0a4d461 100644
--- a/src/tracing/test/api_integrationtest.cc
+++ b/src/tracing/test/api_integrationtest.cc
@@ -1406,7 +1406,7 @@
if (packet.has_track_descriptor()) {
if (packet.trusted_packet_sequence_id() == main_thread_sequence) {
descs.push_back(packet.track_descriptor());
- } else {
+ } else if (packet.track_descriptor().has_thread()) {
thread_descs.push_back(packet.track_descriptor());
}
}
@@ -1431,9 +1431,8 @@
EXPECT_EQ("goodbye.exe", descs[2].name());
// The child thread records only its own thread descriptor (twice, since it
- // was mutated). The child thread also emits another copy of the process
- // descriptor.
- EXPECT_EQ(3u, thread_descs.size());
+ // was mutated).
+ ASSERT_EQ(2u, thread_descs.size());
EXPECT_EQ("TestThread", thread_descs[0].name());
EXPECT_NE(0, thread_descs[0].thread().pid());
EXPECT_NE(0, thread_descs[0].thread().tid());
@@ -1478,7 +1477,8 @@
continue;
if (packet.has_track_descriptor()) {
auto td = packet.track_descriptor();
- EXPECT_TRUE(td.has_process());
+ if (!td.has_process())
+ continue;
EXPECT_NE(0, td.process().pid());
EXPECT_TRUE(td.has_chrome_process());
EXPECT_EQ("testing.exe", td.process().process_name());