diff --git a/init/README.md b/init/README.md index 72b6c6bdd..422fdad5a 100644 --- a/init/README.md +++ b/init/README.md @@ -260,6 +260,14 @@ runs the service. > Sets the child's /proc/self/oom\_score\_adj to the specified value, which must range from -1000 to 1000. +`shutdown ` +> Set shutdown behavior of the service process. When this is not specified, + the service is killed during shutdown process by using SIGTERM and SIGKILL. + The service with shutdown_behavior of "critical" is not killed during shutdown + until shutdown times out. When shutdown times out, even services tagged with + "shutdown critical" will be killed. When the service tagged with "shutdown critical" + is not running when shut down starts, it will be started. + Triggers -------- diff --git a/init/reboot.cpp b/init/reboot.cpp index ec1ddd6f3..38d603ad5 100644 --- a/init/reboot.cpp +++ b/init/reboot.cpp @@ -365,13 +365,15 @@ void DoReboot(unsigned int cmd, const std::string& reason, const std::string& re // keep debugging tools until non critical ones are all gone. const std::set kill_after_apps{"tombstoned", "logd", "adbd"}; // watchdogd is a vendor specific component but should be alive to complete shutdown safely. - const std::set to_starts{"watchdogd", "vold", "ueventd"}; + const std::set to_starts{"watchdogd"}; ServiceManager::GetInstance().ForEachService([&kill_after_apps, &to_starts](Service* s) { if (kill_after_apps.count(s->name())) { s->SetShutdownCritical(); } else if (to_starts.count(s->name())) { s->Start(); s->SetShutdownCritical(); + } else if (s->IsShutdownCritical()) { + s->Start(); // start shutdown critical service if not started } }); diff --git a/init/service.cpp b/init/service.cpp index a2c4b50f1..6b36526ed 100644 --- a/init/service.cpp +++ b/init/service.cpp @@ -501,6 +501,14 @@ bool Service::ParseSetenv(const std::vector& args, std::string* err return true; } +bool Service::ParseShutdown(const std::vector& args, std::string* err) { + if (args[1] == "critical") { + flags_ |= SVC_SHUTDOWN_CRITICAL; + return true; + } + return false; +} + template bool Service::AddDescriptor(const std::vector& args, std::string* err) { int perm = args.size() > 3 ? std::strtoul(args[3].c_str(), 0, 8) : -1; @@ -604,6 +612,7 @@ const Service::OptionParserMap::Map& Service::OptionParserMap::map() const { {"namespace", {1, 2, &Service::ParseNamespace}}, {"seclabel", {1, 1, &Service::ParseSeclabel}}, {"setenv", {2, 2, &Service::ParseSetenv}}, + {"shutdown", {1, 1, &Service::ParseShutdown}}, {"socket", {3, 6, &Service::ParseSocket}}, {"file", {2, 2, &Service::ParseFile}}, {"user", {1, 1, &Service::ParseUser}}, diff --git a/init/service.h b/init/service.h index 0cc16839b..40b4745d9 100644 --- a/init/service.h +++ b/init/service.h @@ -138,6 +138,7 @@ class Service { bool ParseNamespace(const std::vector& args, std::string* err); bool ParseSeclabel(const std::vector& args, std::string* err); bool ParseSetenv(const std::vector& args, std::string* err); + bool ParseShutdown(const std::vector& args, std::string* err); bool ParseSocket(const std::vector& args, std::string* err); bool ParseFile(const std::vector& args, std::string* err); bool ParseUser(const std::vector& args, std::string* err); diff --git a/rootdir/init.rc b/rootdir/init.rc index ae8683420..3893722a8 100644 --- a/rootdir/init.rc +++ b/rootdir/init.rc @@ -691,6 +691,7 @@ service ueventd /sbin/ueventd class core critical seclabel u:r:ueventd:s0 + shutdown critical service healthd /sbin/healthd class core