Added quiet flag for application object
The application object sometimes spews failed to start messages when
executing intensive commands with auto-restart, such as ssh. Although
the nonzero return codes are to be expected, a quiet flag was added as
to reduce the amount of irrelevant messages.
Change-Id: I11b5391b423f1e4763683a2334f9aa75d29b23f8
Signed-off-by: James Kuszmaul <james.kuszmaul@bluerivertech.com>
diff --git a/aos/starter/subprocess.cc b/aos/starter/subprocess.cc
index d907d3f..b7a1cf6 100644
--- a/aos/starter/subprocess.cc
+++ b/aos/starter/subprocess.cc
@@ -102,25 +102,29 @@
Application::Application(std::string_view name,
std::string_view executable_name,
aos::EventLoop *event_loop,
- std::function<void()> on_change)
+ std::function<void()> on_change,
+ QuietLogging quiet_flag)
: name_(name),
path_(executable_name),
event_loop_(event_loop),
start_timer_(event_loop_->AddTimer([this] {
status_ = aos::starter::State::RUNNING;
- LOG(INFO) << "Started '" << name_ << "' pid: " << pid_;
+ LOG_IF(INFO, quiet_flag_ == QuietLogging::kNo)
+ << "Started '" << name_ << "' pid: " << pid_;
})),
restart_timer_(event_loop_->AddTimer([this] { DoStart(); })),
stop_timer_(event_loop_->AddTimer([this] {
if (kill(pid_, SIGKILL) == 0) {
- LOG(WARNING) << "Failed to stop, sending SIGKILL to '" << name_
- << "' pid: " << pid_;
+ LOG_IF(WARNING, quiet_flag_ == QuietLogging::kNo)
+ << "Failed to stop, sending SIGKILL to '" << name_
+ << "' pid: " << pid_;
}
})),
pipe_timer_(event_loop_->AddTimer([this]() { FetchOutputs(); })),
child_status_handler_(
event_loop_->AddTimer([this]() { MaybeHandleSignal(); })),
- on_change_(on_change) {
+ on_change_(on_change),
+ quiet_flag_(quiet_flag) {
event_loop_->OnRun([this]() {
// Every second poll to check if the child is dead. This is used as a
// default for the case where the user is not directly catching SIGCHLD and
@@ -132,12 +136,13 @@
Application::Application(const aos::Application *application,
aos::EventLoop *event_loop,
- std::function<void()> on_change)
+ std::function<void()> on_change,
+ QuietLogging quiet_flag)
: Application(application->name()->string_view(),
application->has_executable_name()
? application->executable_name()->string_view()
: application->name()->string_view(),
- event_loop, on_change) {
+ event_loop, on_change, quiet_flag) {
user_name_ = application->has_user() ? application->user()->str() : "";
user_ = application->has_user() ? FindUid(user_name_.c_str()) : std::nullopt;
group_ = application->has_user() ? FindPrimaryGidForUser(user_name_.c_str())
@@ -179,7 +184,8 @@
if (pid != 0) {
if (pid == -1) {
- PLOG(WARNING) << "Failed to fork '" << name_ << "'";
+ PLOG_IF(WARNING, quiet_flag_ == QuietLogging::kNo)
+ << "Failed to fork '" << name_ << "'";
stop_reason_ = aos::starter::LastStopReason::FORK_ERR;
status_ = aos::starter::State::STOPPED;
} else {
@@ -187,7 +193,8 @@
id_ = next_id_++;
start_time_ = event_loop_->monotonic_now();
status_ = aos::starter::State::STARTING;
- LOG(INFO) << "Starting '" << name_ << "' pid " << pid_;
+ LOG_IF(INFO, quiet_flag_ == QuietLogging::kNo)
+ << "Starting '" << name_ << "' pid " << pid_;
// Set up timer which moves application to RUNNING state if it is still
// alive in 1 second.
@@ -286,7 +293,8 @@
// If we got here, something went wrong
status_pipes_.write->Write(
static_cast<uint32_t>(aos::starter::LastStopReason::EXECV_ERR));
- PLOG(WARNING) << "Could not execute " << name_ << " (" << path_ << ')';
+ PLOG_IF(WARNING, quiet_flag_ == QuietLogging::kNo)
+ << "Could not execute " << name_ << " (" << path_ << ')';
_exit(EXIT_FAILURE);
}
@@ -323,8 +331,9 @@
switch (status_) {
case aos::starter::State::STARTING:
case aos::starter::State::RUNNING: {
- LOG(INFO) << "Stopping '" << name_ << "' pid: " << pid_ << " with signal "
- << SIGINT;
+ LOG_IF(INFO, quiet_flag_ == QuietLogging::kNo)
+ << "Stopping '" << name_ << "' pid: " << pid_ << " with signal "
+ << SIGINT;
status_ = aos::starter::State::STOPPING;
kill(pid_, SIGINT);
@@ -369,7 +378,8 @@
void Application::QueueStart() {
status_ = aos::starter::State::WAITING;
- LOG(INFO) << "Restarting " << name_ << " in 3 seconds";
+ LOG_IF(INFO, quiet_flag_ == QuietLogging::kNo)
+ << "Restarting " << name_ << " in 3 seconds";
restart_timer_->Schedule(event_loop_->monotonic_now() +
std::chrono::seconds(3));
start_timer_->Disable();
@@ -531,11 +541,13 @@
switch (status_) {
case aos::starter::State::STARTING: {
if (exit_code_.value() == 0) {
- LOG(INFO) << "Application '" << name_ << "' pid " << pid_
- << " exited with status " << exit_code_.value();
+ LOG_IF(INFO, quiet_flag_ == QuietLogging::kNo)
+ << "Application '" << name_ << "' pid " << pid_
+ << " exited with status " << exit_code_.value();
} else {
- LOG(WARNING) << "Failed to start '" << name_ << "' on pid " << pid_
- << " : Exited with status " << exit_code_.value();
+ LOG_IF(WARNING, quiet_flag_ == QuietLogging::kNo)
+ << "Failed to start '" << name_ << "' on pid " << pid_
+ << " : Exited with status " << exit_code_.value();
}
if (autorestart()) {
QueueStart();
@@ -547,12 +559,13 @@
}
case aos::starter::State::RUNNING: {
if (exit_code_.value() == 0) {
- LOG(INFO) << "Application '" << name_ << "' pid " << pid_
- << " exited with status " << exit_code_.value();
+ LOG_IF(INFO, quiet_flag_ == QuietLogging::kNo)
+ << "Application '" << name_ << "' pid " << pid_
+ << " exited with status " << exit_code_.value();
} else {
- LOG(WARNING) << "Application '" << name_ << "' pid " << pid_
- << " exited unexpectedly with status "
- << exit_code_.value();
+ LOG_IF(WARNING, quiet_flag_ == QuietLogging::kNo)
+ << "Application '" << name_ << "' pid " << pid_
+ << " exited unexpectedly with status " << exit_code_.value();
}
if (autorestart()) {
QueueStart();
@@ -563,8 +576,9 @@
break;
}
case aos::starter::State::STOPPING: {
- LOG(INFO) << "Successfully stopped '" << name_ << "' pid: " << pid_
- << " with status " << exit_code_.value();
+ LOG_IF(INFO, quiet_flag_ == QuietLogging::kNo)
+ << "Successfully stopped '" << name_ << "' pid: " << pid_
+ << " with status " << exit_code_.value();
status_ = aos::starter::State::STOPPED;
// Disable force stop timer since the process already died
diff --git a/aos/starter/subprocess.h b/aos/starter/subprocess.h
index 1f16168..60732c3 100644
--- a/aos/starter/subprocess.h
+++ b/aos/starter/subprocess.h
@@ -55,15 +55,18 @@
// automatically.
class Application {
public:
+ enum class QuietLogging { kYes, kNo };
Application(const aos::Application *application, aos::EventLoop *event_loop,
- std::function<void()> on_change);
+ std::function<void()> on_change,
+ QuietLogging quiet_flag = QuietLogging::kNo);
// executable_name is the actual executable path.
// When sudo is not used, name is used as argv[0] when exec'ing
// executable_name. When sudo is used it's not possible to pass in a
// distinct argv[0].
Application(std::string_view name, std::string_view executable_name,
- aos::EventLoop *event_loop, std::function<void()> on_change);
+ aos::EventLoop *event_loop, std::function<void()> on_change,
+ QuietLogging quiet_flag = QuietLogging::kNo);
flatbuffers::Offset<aos::starter::ApplicationStatus> PopulateStatus(
flatbuffers::FlatBufferBuilder *builder, util::Top *top);
@@ -179,6 +182,8 @@
std::unique_ptr<MemoryCGroup> memory_cgroup_;
+ QuietLogging quiet_flag_ = QuietLogging::kNo;
+
DISALLOW_COPY_AND_ASSIGN(Application);
};
diff --git a/aos/starter/subprocess_test.cc b/aos/starter/subprocess_test.cc
index 3633d1f..4aa371b 100644
--- a/aos/starter/subprocess_test.cc
+++ b/aos/starter/subprocess_test.cc
@@ -100,4 +100,83 @@
ASSERT_EQ(aos::starter::State::STOPPED, echo_stderr.status());
}
+TEST_F(SubprocessTest, UnactiveQuietFlag) {
+ const std::string config_file =
+ ::aos::testing::ArtifactPath("aos/events/pingpong_config.json");
+
+ ::testing::internal::CaptureStderr();
+
+ // Set up application without quiet flag active
+ aos::FlatbufferDetachedBuffer<aos::Configuration> config =
+ aos::configuration::ReadConfig(config_file);
+ aos::ShmEventLoop event_loop(&config.message());
+ bool observed_stopped = false;
+ Application error_out(
+ "false", "false", &event_loop,
+ [&observed_stopped, &error_out]() {
+ if (error_out.status() == aos::starter::State::STOPPED) {
+ observed_stopped = true;
+ }
+ },
+ Application::QuietLogging::kNo);
+ ASSERT_FALSE(error_out.autorestart());
+
+ error_out.Start();
+ aos::TimerHandler *exit_timer =
+ event_loop.AddTimer([&event_loop]() { event_loop.Exit(); });
+ event_loop.OnRun([&event_loop, exit_timer]() {
+ exit_timer->Schedule(event_loop.monotonic_now() +
+ std::chrono::milliseconds(1500));
+ });
+
+ event_loop.Run();
+
+ // Ensure presence of logs without quiet flag
+ std::string output = ::testing::internal::GetCapturedStderr();
+ std::string expectedStart = "Failed to start 'false'";
+ std::string expectedRun = "exited unexpectedly with status";
+
+ ASSERT_TRUE(output.find(expectedStart) != std::string::npos ||
+ output.find(expectedRun) != std::string::npos);
+ EXPECT_TRUE(observed_stopped);
+ EXPECT_EQ(aos::starter::State::STOPPED, error_out.status());
+}
+
+TEST_F(SubprocessTest, ActiveQuietFlag) {
+ const std::string config_file =
+ ::aos::testing::ArtifactPath("aos/events/pingpong_config.json");
+
+ ::testing::internal::CaptureStderr();
+
+ // Set up application with quiet flag active
+ aos::FlatbufferDetachedBuffer<aos::Configuration> config =
+ aos::configuration::ReadConfig(config_file);
+ aos::ShmEventLoop event_loop(&config.message());
+ bool observed_stopped = false;
+ Application error_out(
+ "false", "false", &event_loop,
+ [&observed_stopped, &error_out]() {
+ if (error_out.status() == aos::starter::State::STOPPED) {
+ observed_stopped = true;
+ }
+ },
+ Application::QuietLogging::kYes);
+ ASSERT_FALSE(error_out.autorestart());
+
+ error_out.Start();
+ aos::TimerHandler *exit_timer =
+ event_loop.AddTimer([&event_loop]() { event_loop.Exit(); });
+ event_loop.OnRun([&event_loop, exit_timer]() {
+ exit_timer->Schedule(event_loop.monotonic_now() +
+ std::chrono::milliseconds(1500));
+ });
+
+ event_loop.Run();
+
+ // Ensure lack of logs with quiet flag
+ ASSERT_TRUE(::testing::internal::GetCapturedStderr().empty());
+ EXPECT_TRUE(observed_stopped);
+ EXPECT_EQ(aos::starter::State::STOPPED, error_out.status());
+}
+
} // namespace aos::starter::testing