Merge "Do not set -latomic for !use_custom_libcxx"
diff --git a/include/perfetto/ftrace_reader/ftrace_controller.h b/include/perfetto/ftrace_reader/ftrace_controller.h
index ce9c6cb..7de9e53 100644
--- a/include/perfetto/ftrace_reader/ftrace_controller.h
+++ b/include/perfetto/ftrace_reader/ftrace_controller.h
@@ -42,6 +42,9 @@
 
 const size_t kMaxSinks = 32;
 
+// Method of last resort to reset ftrace state.
+void HardResetFtraceState();
+
 class FtraceController;
 class ProtoTranslationTable;
 class CpuReader;
diff --git a/src/ftrace_reader/ftrace_controller.cc b/src/ftrace_reader/ftrace_controller.cc
index ee9252c..195509b 100644
--- a/src/ftrace_reader/ftrace_controller.cc
+++ b/src/ftrace_reader/ftrace_controller.cc
@@ -22,6 +22,7 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/wait.h>
+#include <unistd.h>
 
 #include <array>
 #include <string>
@@ -107,8 +108,39 @@
   return status == 0;
 }
 
+void WriteToFile(const char* path, const char* str) {
+  int fd = open(path, O_WRONLY);
+  if (fd == -1)
+    return;
+  write(fd, str, strlen(str));
+  close(fd);
+}
+
+void ClearFile(const char* path) {
+  int fd = open(path, O_WRONLY | O_TRUNC);
+  if (fd == -1)
+    return;
+  close(fd);
+}
+
 }  // namespace
 
+// TODO(fmayer): Actually call this on shutdown.
+// Method of last resort to reset ftrace state.
+// We don't know what state the rest of the system and process is so as far
+// as possible avoid allocations.
+void HardResetFtraceState() {
+  WriteToFile("/sys/kernel/debug/tracing/tracing_on", "0");
+  WriteToFile("/sys/kernel/debug/tracing/buffer_size_kb", "4");
+  WriteToFile("/sys/kernel/debug/tracing/events/enable", "0");
+  ClearFile("/sys/kernel/debug/tracing/trace");
+
+  WriteToFile("/sys/kernel/tracing/tracing_on", "0");
+  WriteToFile("/sys/kernel/tracing/buffer_size_kb", "4");
+  WriteToFile("/sys/kernel/tracing/events/enable", "0");
+  ClearFile("/sys/kernel/tracing/trace");
+}
+
 // static
 // TODO(taylori): Add a test for tracing paths in integration tests.
 std::unique_ptr<FtraceController> FtraceController::Create(
diff --git a/src/ftrace_reader/ftrace_procfs_integrationtest.cc b/src/ftrace_reader/ftrace_procfs_integrationtest.cc
index 620cd87..1527308 100644
--- a/src/ftrace_reader/ftrace_procfs_integrationtest.cc
+++ b/src/ftrace_reader/ftrace_procfs_integrationtest.cc
@@ -22,6 +22,7 @@
 #include "ftrace_procfs.h"
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
+#include "perfetto/ftrace_reader/ftrace_controller.h"
 
 using testing::HasSubstr;
 using testing::Not;
@@ -151,4 +152,26 @@
   EXPECT_EQ(ReadFile("buffer_size_kb"), "20\n");  // (4096 * 5) / 1024
 }
 
+TEST(FtraceProcfsIntegrationTest, FtraceControllerHardReset) {
+  FtraceProcfs ftrace(kTracingPath);
+  ResetFtrace(&ftrace);
+
+  ftrace.SetCpuBufferSizeInPages(4ul);
+  ftrace.EnableTracing();
+  ftrace.EnableEvent("sched", "sched_switch");
+  ftrace.WriteTraceMarker("Hello, World!");
+
+  EXPECT_EQ(ReadFile("buffer_size_kb"), "16\n");
+  EXPECT_EQ(ReadFile("tracing_on"), "1\n");
+  EXPECT_EQ(ReadFile("events/enable"), "X\n");
+  EXPECT_THAT(GetTraceOutput(), HasSubstr("Hello"));
+
+  HardResetFtraceState();
+
+  EXPECT_EQ(ReadFile("buffer_size_kb"), "4\n");
+  EXPECT_EQ(ReadFile("tracing_on"), "0\n");
+  EXPECT_EQ(ReadFile("events/enable"), "0\n");
+  EXPECT_THAT(GetTraceOutput(), Not(HasSubstr("Hello")));
+}
+
 }  // namespace perfetto
diff --git a/src/traced/probes/ftrace_producer.h b/src/traced/probes/ftrace_producer.h
index 27c292a..95c9a99 100644
--- a/src/traced/probes/ftrace_producer.h
+++ b/src/traced/probes/ftrace_producer.h
@@ -60,8 +60,11 @@
 
    private:
     std::unique_ptr<FtraceSink> sink_ = nullptr;
-    TraceWriter::TracePacketHandle trace_packet_;
     std::unique_ptr<TraceWriter> writer_;
+
+    // Keep this after the TraceWriter because TracePackets must not outlive
+    // their originating writer.
+    TraceWriter::TracePacketHandle trace_packet_;
   };
 
   enum State {
diff --git a/src/tracing/core/trace_writer_impl.cc b/src/tracing/core/trace_writer_impl.cc
index f38128e..3bd4199 100644
--- a/src/tracing/core/trace_writer_impl.cc
+++ b/src/tracing/core/trace_writer_impl.cc
@@ -18,6 +18,7 @@
 
 #include <string.h>
 
+#include <algorithm>
 #include <type_traits>
 #include <utility>
 
diff --git a/test/AndroidTest.xml b/test/AndroidTest.xml
index 3f2a230..8f529af 100644
--- a/test/AndroidTest.xml
+++ b/test/AndroidTest.xml
@@ -21,10 +21,7 @@
         <option name="push" value="perfetto_unittests->/data/local/tmp/perfetto_unittests" />
         <option name="push" value="perfetto_integrationtests->/data/local/tmp/perfetto_integrationtests" />
     </target_preparer>
-    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
-        <option name="run-command" value="setprop persist.traced.enable 1" />
-        <option name="teardown-command" value="setprop persist.traced.enable 0" />
-    </target_preparer>
+    <option name="post-boot-command" value="setprop persist.traced.enable 1" />
     <test class="com.android.tradefed.testtype.GTest" >
       <option name="native-test-device-path" value="/data/local/tmp/perfetto_unittests" />
       <option name="module-name" value="perfetto_unittests" />