Add support for autorestart in aos_starter
We have applications which we want to run only once (at startup or
during runtime). This enables the user to configure the state machine
to support the behavior they want.
Change-Id: Ica59338956eb1cadd2edac49fbdac51b56aa516a
Signed-off-by: James Kuszmaul <james.kuszmaul@bluerivertech.com>
diff --git a/aos/starter/BUILD b/aos/starter/BUILD
index 73353f6..ec323a9 100644
--- a/aos/starter/BUILD
+++ b/aos/starter/BUILD
@@ -65,7 +65,7 @@
"//aos/events:pong",
],
linkopts = ["-lstdc++fs"],
- shard_count = 3,
+ shard_count = 4,
# The roborio compiler doesn't support <filesystem>.
target_compatible_with =
select({
diff --git a/aos/starter/starter_test.cc b/aos/starter/starter_test.cc
index f434e84..120fe38 100644
--- a/aos/starter/starter_test.cc
+++ b/aos/starter/starter_test.cc
@@ -316,5 +316,95 @@
starterd_thread.join();
}
+// Tests that starterd respects autorestart.
+TEST_F(StarterdTest, DeathNoRestartTest) {
+ const std::string config_file =
+ ArtifactPath("aos/events/pingpong_config.json");
+
+ aos::FlatbufferDetachedBuffer<aos::Configuration> config =
+ aos::configuration::ReadConfig(config_file);
+
+ const std::string test_dir = aos::testing::TestTmpDir();
+
+ auto new_config = aos::configuration::MergeWithConfig(
+ &config.message(), absl::StrFormat(
+ R"({"applications": [
+ {
+ "name": "ping",
+ "executable_name": "%s",
+ "args": ["--shm_base", "%s/aos"],
+ "autorestart": false
+ },
+ {
+ "name": "pong",
+ "executable_name": "%s",
+ "args": ["--shm_base", "%s/aos"]
+ }
+ ]})",
+ ArtifactPath("aos/events/ping"), test_dir,
+ ArtifactPath("aos/events/pong"), test_dir));
+
+ const aos::Configuration *config_msg = &new_config.message();
+
+ // Set up starter with config file
+ aos::starter::Starter starter(config_msg);
+
+ // Create an event loop to watch for the Status message to watch the state
+ // transitions.
+ aos::ShmEventLoop watcher_loop(config_msg);
+ watcher_loop.SkipAosLog();
+
+ watcher_loop
+ .AddTimer([&watcher_loop] {
+ watcher_loop.Exit();
+ SUCCEED();
+ })
+ ->Setup(watcher_loop.monotonic_now() + std::chrono::seconds(11));
+
+ int test_stage = 0;
+ uint64_t id;
+
+ watcher_loop.MakeWatcher("/aos", [&test_stage, &watcher_loop,
+ &id](const aos::starter::Status &status) {
+ const aos::starter::ApplicationStatus *app_status =
+ FindApplicationStatus(status, "ping");
+ if (app_status == nullptr) {
+ return;
+ }
+
+ switch (test_stage) {
+ case 0: {
+ if (app_status->has_state() &&
+ app_status->state() == aos::starter::State::RUNNING) {
+ LOG(INFO) << "Ping is running";
+ test_stage = 1;
+ ASSERT_TRUE(app_status->has_pid());
+ ASSERT_TRUE(kill(app_status->pid(), SIGINT) != -1);
+ ASSERT_TRUE(app_status->has_id());
+ id = app_status->id();
+ }
+ break;
+ }
+
+ case 1: {
+ if (app_status->has_state() &&
+ app_status->state() == aos::starter::State::RUNNING &&
+ app_status->has_id() && app_status->id() != id) {
+ LOG(INFO) << "Ping restarted, it shouldn't...";
+ watcher_loop.Exit();
+ FAIL();
+ }
+ break;
+ }
+ }
+ });
+
+ std::thread starterd_thread([&starter] { starter.Run(); });
+ watcher_loop.Run();
+
+ starter.Cleanup();
+ starterd_thread.join();
+}
+
} // namespace starter
} // namespace aos
diff --git a/aos/starter/starterd_lib.cc b/aos/starter/starterd_lib.cc
index 00b094f..b7c49ed 100644
--- a/aos/starter/starterd_lib.cc
+++ b/aos/starter/starterd_lib.cc
@@ -31,6 +31,7 @@
group_(application->has_user() ? FindPrimaryGidForUser(user_name_.c_str())
: std::nullopt),
autostart_(application->autostart()),
+ autorestart_(application->autorestart()),
event_loop_(event_loop),
start_timer_(event_loop_->AddTimer([this] {
status_ = aos::starter::State::RUNNING;
@@ -319,13 +320,17 @@
case aos::starter::State::STARTING: {
LOG(WARNING) << "Failed to start '" << name_ << "' on pid " << pid_
<< " : Exited with status " << exit_code_;
- QueueStart();
+ if (autorestart()) {
+ QueueStart();
+ }
break;
}
case aos::starter::State::RUNNING: {
LOG(WARNING) << "Application '" << name_ << "' pid " << pid_
<< " exited unexpectedly with status " << exit_code_;
- QueueStart();
+ if (autorestart()) {
+ QueueStart();
+ }
break;
}
case aos::starter::State::STOPPING: {
diff --git a/aos/starter/starterd_lib.h b/aos/starter/starterd_lib.h
index 8c70960..e1f82a0 100644
--- a/aos/starter/starterd_lib.h
+++ b/aos/starter/starterd_lib.h
@@ -97,6 +97,8 @@
bool autostart() const { return autostart_; }
+ bool autorestart() const { return autorestart_; }
+
private:
void DoStart();
@@ -130,6 +132,7 @@
bool queue_restart_ = false;
bool terminating_ = false;
bool autostart_ = true;
+ bool autorestart_ = true;
aos::starter::State status_ = aos::starter::State::STOPPED;
aos::starter::LastStopReason stop_reason_ =