perfetto_cmd: don't connect to the service if unnecessary
The previous refactoring aosp/1713963 introduced a bug
in the perfetto cmdline client. The bug was about assuming
that a 0 return code from the cmdline parser meant
"all clear, proceed with the service connection".
However, there were two cases where previously a return 0
mean to exit(0) without connecting:
--version and --reset-guardrails.
The CL makes the ParseCmdlineAndMaybeDaemonize return
an Optional<int> so it's clear if intends to exit()
or continue.
Test: added a test to perfetto_integrationtests,
checked it failed before this CL.
Bug: 189359657
Bug: 158465724
Bug: 187945217
Change-Id: I765dd36dc9b69576ec3e888dfa2893ea31a7b6e5
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/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);