Merge "docs: Fix small typo in table comments"
diff --git a/debian/control b/debian/control
index 94a03bb..00f1346 100644
--- a/debian/control
+++ b/debian/control
@@ -7,6 +7,7 @@
   git,
   libprotoc-dev,
   ninja-build,
+  pandoc,
   protobuf-compiler,
   python3,
   zlib1g-dev,
diff --git a/debian/perfetto.manpages b/debian/perfetto.manpages
new file mode 100644
index 0000000..07cb459
--- /dev/null
+++ b/debian/perfetto.manpages
@@ -0,0 +1 @@
+debian/perfetto.1
diff --git a/debian/rules b/debian/rules
index a081c5c..f8d21e0 100755
--- a/debian/rules
+++ b/debian/rules
@@ -34,6 +34,8 @@
 
 override_dh_auto_build:
 	ninja -C out/release perfetto traced traced_probes
+	pandoc docs/reference/perfetto-cli.md -s -t man --shift-heading-level-by=-1 >\
+	 debian/perfetto.1
 
 override_dh_auto_clean:
 	rm -rf out/release
diff --git a/docs/reference/heap_profile-cli.md b/docs/reference/heap_profile-cli.md
index 18b4f74..7a68ea2 100644
--- a/docs/reference/heap_profile-cli.md
+++ b/docs/reference/heap_profile-cli.md
@@ -1,4 +1,8 @@
-# heap_profile(1)
+# HEAP_PROFILE(1)
+
+## NAME
+
+heap_profile - record heap profile on Android device
 
 ## DESCRIPTION
 
diff --git a/src/perfetto_cmd/perfetto_cmd.cc b/src/perfetto_cmd/perfetto_cmd.cc
index c6fe500..6bca082 100644
--- a/src/perfetto_cmd/perfetto_cmd.cc
+++ b/src/perfetto_cmd/perfetto_cmd.cc
@@ -176,7 +176,7 @@
   g_perfetto_cmd = nullptr;
 }
 
-int PerfettoCmd::PrintUsage(const char* argv0) {
+void PerfettoCmd::PrintUsage(const char* argv0) {
   fprintf(stderr, R"(
 Usage: %s
   --background     -d      : Exits immediately and continues in the background.
@@ -225,10 +225,10 @@
                           Exit code:  0:Yes, 2:No, 1:Error.
 )", /* this comment fixes syntax highlighting in some editors */
           argv0);
-  return 1;
 }
 
-int PerfettoCmd::ParseCmdlineAndMaybeDaemonize(int argc, char** argv) {
+base::Optional<int> PerfettoCmd::ParseCmdlineAndMaybeDaemonize(int argc,
+                                                               char** argv) {
 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
   umask(0000);  // make sure that file creation is not affected by umask.
 #endif
@@ -459,7 +459,8 @@
       continue;
     }
 
-    return PrintUsage(argv[0]);
+    PrintUsage(argv[0]);
+    return 1;
   }
 
   for (ssize_t i = optind; i < argc; i++) {
@@ -693,7 +694,7 @@
     base::Daemonize();
   }
 
-  return 0;  // Continues in ConnectToServiceAndRun() below.
+  return base::nullopt;  // Continues in ConnectToServiceAndRun() below.
 }
 
 int PerfettoCmd::ConnectToServiceAndRun() {
@@ -1095,9 +1096,9 @@
 
 int PERFETTO_EXPORT_ENTRYPOINT PerfettoCmdMain(int argc, char** argv) {
   perfetto::PerfettoCmd cmd;
-  int res = cmd.ParseCmdlineAndMaybeDaemonize(argc, argv);
-  if (res)
-    return res;
+  auto opt_res = cmd.ParseCmdlineAndMaybeDaemonize(argc, argv);
+  if (opt_res.has_value())
+    return *opt_res;
   return cmd.ConnectToServiceAndRun();
 }
 
diff --git a/src/perfetto_cmd/perfetto_cmd.h b/src/perfetto_cmd/perfetto_cmd.h
index 4087f49..f1bfe5b 100644
--- a/src/perfetto_cmd/perfetto_cmd.h
+++ b/src/perfetto_cmd/perfetto_cmd.h
@@ -50,7 +50,10 @@
   // The main() is split in two stages: cmdline parsing and actual interaction
   // with traced. This is to allow tools like tracebox to avoid spawning the
   // service for no reason if the cmdline parsing fails.
-  int ParseCmdlineAndMaybeDaemonize(int argc, char** argv);
+  // Return value:
+  //   nullopt: no error, the caller should call ConnectToServiceAndRun.
+  //   0-N: the caller should exit() with the given exit code.
+  base::Optional<int> ParseCmdlineAndMaybeDaemonize(int argc, char** argv);
   int ConnectToServiceAndRun();
 
   // perfetto::Consumer implementation.
@@ -69,7 +72,7 @@
   bool OpenOutputFile();
   void SetupCtrlCSignalHandler();
   void FinalizeTraceAndExit();
-  int PrintUsage(const char* argv0);
+  void PrintUsage(const char* argv0);
   void PrintServiceState(bool success, const TracingServiceState&);
   void OnTimeout();
   bool is_detach() const { return !detach_key_.empty(); }
diff --git a/src/trace_processor/iterator_impl.cc b/src/trace_processor/iterator_impl.cc
index 6539e9a..c0b3aac 100644
--- a/src/trace_processor/iterator_impl.cc
+++ b/src/trace_processor/iterator_impl.cc
@@ -34,7 +34,7 @@
       db_(db),
       stmt_(std::move(stmt)),
       column_count_(column_count),
-      status_(status),
+      status_(std::move(status)),
       sql_stats_row_(sql_stats_row) {}
 
 IteratorImpl::~IteratorImpl() {
diff --git a/src/trace_processor/trace_processor_shell.cc b/src/trace_processor/trace_processor_shell.cc
index e4fac8b..9db56c4 100644
--- a/src/trace_processor/trace_processor_shell.cc
+++ b/src/trace_processor/trace_processor_shell.cc
@@ -580,6 +580,7 @@
     if (it.Next()) {
       return util::ErrStatus("Unexpected result from a query.");
     }
+    RETURN_IF_ERROR(it.Status());
   }
   return util::OkStatus();
 }
@@ -600,6 +601,7 @@
     RETURN_IF_ERROR(it.Status());
     if (it.ColumnCount() == 0) {
       bool it_has_more = it.Next();
+      RETURN_IF_ERROR(it.Status());
       PERFETTO_DCHECK(!it_has_more);
       continue;
     }
diff --git a/src/tracebox/tracebox.cc b/src/tracebox/tracebox.cc
index f99aaa8..ab2cae8 100644
--- a/src/tracebox/tracebox.cc
+++ b/src/tracebox/tracebox.cc
@@ -125,9 +125,9 @@
   // spawned by the damonized cmdline client, which is what we want so killing
   // the backgrounded cmdline client will also kill the other services, as they
   // will live in the same background session.
-  int res = perfetto_cmd.ParseCmdlineAndMaybeDaemonize(argc, argv);
-  if (res)
-    return res;
+  auto opt_res = perfetto_cmd.ParseCmdlineAndMaybeDaemonize(argc, argv);
+  if (opt_res.has_value())
+    return *opt_res;
 
   std::string self_path = base::GetCurExecutablePath();
   base::Subprocess traced({self_path, "traced"});
diff --git a/test/end_to_end_integrationtest.cc b/test/end_to_end_integrationtest.cc
index af54f08..435690d 100644
--- a/test/end_to_end_integrationtest.cc
+++ b/test/end_to_end_integrationtest.cc
@@ -1176,6 +1176,11 @@
   EXPECT_THAT(stderr_, HasSubstr("Cannot specify a trace config"));
 }
 
+TEST_F(PerfettoCmdlineTest, NoSanitizers(Version)) {
+  auto perfetto = ExecPerfetto({"--version"});
+  EXPECT_EQ(0, perfetto.Run(&stderr_)) << stderr_;
+}
+
 TEST_F(PerfettoCmdlineTest, NoSanitizers(TxtConfig)) {
   std::string cfg("duration_ms: 100");
   auto perfetto = ExecPerfetto({"-c", "-", "--txt", "-o", "-"}, cfg);