Merge "Backtrace: Add libziparchive dependency"
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 8c19a81..ba30756 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -476,10 +476,11 @@
if ((info.st_mode & S_IFMT) == S_IFLNK)
unlink(target);
mkdir(target, 0755);
+ errno = 0;
ret = mount(source, target, rec->fs_type, mountflags, rec->fs_options);
save_errno = errno;
- LINFO << __FUNCTION__ << "(source=" << source << ",target="
- << target << ",type=" << rec->fs_type << ")=" << ret;
+ PINFO << __FUNCTION__ << "(source=" << source << ",target=" << target
+ << ",type=" << rec->fs_type << ")=" << ret;
if ((ret == 0) && (mountflags & MS_RDONLY) != 0) {
fs_mgr_set_blk_ro(source);
}
diff --git a/init/action.cpp b/init/action.cpp
index 6900391..4a3ab48 100644
--- a/init/action.cpp
+++ b/init/action.cpp
@@ -326,6 +326,13 @@
}
}
+void ActionManager::ClearQueue() {
+ // We are shutting down so don't claim the oneshot builtin actions back
+ current_executing_actions_ = {};
+ event_queue_ = {};
+ current_command_ = 0;
+}
+
bool ActionParser::ParseSection(std::vector<std::string>&& args, const std::string& filename,
int line, std::string* err) {
std::vector<std::string> triggers(args.begin() + 1, args.end());
diff --git a/init/action.h b/init/action.h
index 5cb50a7..ad15f3f 100644
--- a/init/action.h
+++ b/init/action.h
@@ -104,6 +104,7 @@
void ExecuteOneCommand();
bool HasMoreCommands() const;
void DumpState() const;
+ void ClearQueue();
private:
ActionManager(ActionManager const&) = delete;
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 00ffbc3..75a8f19 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -119,7 +119,7 @@
LOG(ERROR) << "failed to set bootloader message: " << err;
return -1;
}
- DoReboot(ANDROID_RB_RESTART2, "reboot", "recovery", false);
+ property_set("sys.powerctl", "reboot,recovery");
return 0;
}
diff --git a/init/devices.cpp b/init/devices.cpp
index 215d2ea..13cf991 100644
--- a/init/devices.cpp
+++ b/init/devices.cpp
@@ -219,7 +219,7 @@
return {0600, 0, 0};
}
-void DeviceHandler::MakeDevice(const std::string& path, int block, int major, int minor,
+void DeviceHandler::MakeDevice(const std::string& path, bool block, int major, int minor,
const std::vector<std::string>& links) const {
auto[mode, uid, gid] = GetDevicePermissions(path, links);
mode |= (block ? S_IFBLK : S_IFCHR);
@@ -279,45 +279,6 @@
}
}
-std::vector<std::string> DeviceHandler::GetCharacterDeviceSymlinks(const Uevent& uevent) const {
- std::string parent_device;
- if (!FindPlatformDevice(uevent.path, &parent_device)) return {};
-
- // skip path to the parent driver
- std::string path = uevent.path.substr(parent_device.length());
-
- if (!StartsWith(path, "/usb")) return {};
-
- // skip root hub name and device. use device interface
- // skip 3 slashes, including the first / by starting the search at the 1st character, not 0th.
- // then extract what comes between the 3rd and 4th slash
- // e.g. "/usb/usb_device/name/tty2-1:1.0" -> "name"
-
- std::string::size_type start = 0;
- start = path.find('/', start + 1);
- if (start == std::string::npos) return {};
-
- start = path.find('/', start + 1);
- if (start == std::string::npos) return {};
-
- auto end = path.find('/', start + 1);
- if (end == std::string::npos) return {};
-
- start++; // Skip the first '/'
-
- auto length = end - start;
- if (length == 0) return {};
-
- auto name_string = path.substr(start, length);
-
- std::vector<std::string> links;
- links.emplace_back("/dev/usb/" + uevent.subsystem + name_string);
-
- mkdir("/dev/usb", 0755);
-
- return links;
-}
-
// replaces any unacceptable characters with '_', the
// length of the resulting string is equal to the input string
void SanitizePartitionName(std::string* string) {
@@ -385,7 +346,7 @@
return links;
}
-void DeviceHandler::HandleDevice(const std::string& action, const std::string& devpath, int block,
+void DeviceHandler::HandleDevice(const std::string& action, const std::string& devpath, bool block,
int major, int minor, const std::vector<std::string>& links) const {
if (action == "add") {
MakeDevice(devpath, block, major, minor, links);
@@ -411,31 +372,26 @@
}
}
-void DeviceHandler::HandleBlockDeviceEvent(const Uevent& uevent) const {
- // if it's not a /dev device, nothing to do
- if (uevent.major < 0 || uevent.minor < 0) return;
-
- const char* base = "/dev/block/";
- make_dir(base, 0755, sehandle_);
-
- std::string name = Basename(uevent.path);
- std::string devpath = base + name;
-
- std::vector<std::string> links;
- if (StartsWith(uevent.path, "/devices")) {
- links = GetBlockDeviceSymlinks(uevent);
+void DeviceHandler::HandleDeviceEvent(const Uevent& uevent) {
+ if (uevent.action == "add" || uevent.action == "change" || uevent.action == "online") {
+ FixupSysPermissions(uevent.path, uevent.subsystem);
}
- HandleDevice(uevent.action, devpath, 1, uevent.major, uevent.minor, links);
-}
-
-void DeviceHandler::HandleGenericDeviceEvent(const Uevent& uevent) const {
// if it's not a /dev device, nothing to do
if (uevent.major < 0 || uevent.minor < 0) return;
std::string devpath;
+ std::vector<std::string> links;
+ bool block = false;
- if (StartsWith(uevent.subsystem, "usb")) {
+ if (uevent.subsystem == "block") {
+ block = true;
+ devpath = "/dev/block/" + Basename(uevent.path);
+
+ if (StartsWith(uevent.path, "/devices")) {
+ links = GetBlockDeviceSymlinks(uevent);
+ }
+ } else if (StartsWith(uevent.subsystem, "usb")) {
if (uevent.subsystem == "usb") {
if (!uevent.device_name.empty()) {
devpath = "/dev/" + uevent.device_name;
@@ -461,21 +417,7 @@
mkdir_recursive(Dirname(devpath), 0755, sehandle_);
- auto links = GetCharacterDeviceSymlinks(uevent);
-
- HandleDevice(uevent.action, devpath, 0, uevent.major, uevent.minor, links);
-}
-
-void DeviceHandler::HandleDeviceEvent(const Uevent& uevent) {
- if (uevent.action == "add" || uevent.action == "change" || uevent.action == "online") {
- FixupSysPermissions(uevent.path, uevent.subsystem);
- }
-
- if (uevent.subsystem == "block") {
- HandleBlockDeviceEvent(uevent);
- } else {
- HandleGenericDeviceEvent(uevent);
- }
+ HandleDevice(uevent.action, devpath, block, uevent.major, uevent.minor, links);
}
DeviceHandler::DeviceHandler(std::vector<Permissions> dev_permissions,
diff --git a/init/devices.h b/init/devices.h
index 5105ad7..c64f5fb 100644
--- a/init/devices.h
+++ b/init/devices.h
@@ -115,16 +115,12 @@
bool FindPlatformDevice(std::string path, std::string* platform_device_path) const;
std::tuple<mode_t, uid_t, gid_t> GetDevicePermissions(
const std::string& path, const std::vector<std::string>& links) const;
- void MakeDevice(const std::string& path, int block, int major, int minor,
+ void MakeDevice(const std::string& path, bool block, int major, int minor,
const std::vector<std::string>& links) const;
- std::vector<std::string> GetCharacterDeviceSymlinks(const Uevent& uevent) const;
- void HandleDevice(const std::string& action, const std::string& devpath, int block, int major,
+ void HandleDevice(const std::string& action, const std::string& devpath, bool block, int major,
int minor, const std::vector<std::string>& links) const;
void FixupSysPermissions(const std::string& upath, const std::string& subsystem) const;
- void HandleBlockDeviceEvent(const Uevent& uevent) const;
- void HandleGenericDeviceEvent(const Uevent& uevent) const;
-
std::vector<Permissions> dev_permissions_;
std::vector<SysfsPermissions> sysfs_permissions_;
std::vector<Subsystem> subsystems_;
diff --git a/init/devices_test.cpp b/init/devices_test.cpp
index 57d8e0f..ac4ab9b 100644
--- a/init/devices_test.cpp
+++ b/init/devices_test.cpp
@@ -30,7 +30,7 @@
class DeviceHandlerTester {
public:
void TestGetSymlinks(const std::string& platform_device, const Uevent& uevent,
- const std::vector<std::string> expected_links, bool block) {
+ const std::vector<std::string> expected_links) {
TemporaryDir fake_sys_root;
device_handler_.sysfs_mount_point_ = fake_sys_root.path;
@@ -44,11 +44,7 @@
mkdir_recursive(android::base::Dirname(fake_sys_root.path + uevent.path), 0777, nullptr);
std::vector<std::string> result;
- if (block) {
- result = device_handler_.GetBlockDeviceSymlinks(uevent);
- } else {
- result = device_handler_.GetCharacterDeviceSymlinks(uevent);
- }
+ result = device_handler_.GetBlockDeviceSymlinks(uevent);
auto expected_size = expected_links.size();
ASSERT_EQ(expected_size, result.size());
@@ -64,95 +60,6 @@
DeviceHandler device_handler_;
};
-TEST(device_handler, get_character_device_symlinks_success) {
- const char* platform_device = "/devices/platform/some_device_name";
- Uevent uevent = {
- .path = "/devices/platform/some_device_name/usb/usb_device/name/tty2-1:1.0",
- .subsystem = "tty",
- };
- std::vector<std::string> expected_result{"/dev/usb/ttyname"};
-
- DeviceHandlerTester device_handler_tester_;
- device_handler_tester_.TestGetSymlinks(platform_device, uevent, expected_result, false);
-}
-
-TEST(device_handler, get_character_device_symlinks_no_pdev_match) {
- const char* platform_device = "/devices/platform/some_device_name";
- Uevent uevent = {
- .path = "/device/name/tty2-1:1.0", .subsystem = "tty",
- };
- std::vector<std::string> expected_result;
-
- DeviceHandlerTester device_handler_tester_;
- device_handler_tester_.TestGetSymlinks(platform_device, uevent, expected_result, false);
-}
-
-TEST(device_handler, get_character_device_symlinks_nothing_after_platform_device) {
- const char* platform_device = "/devices/platform/some_device_name";
- Uevent uevent = {
- .path = "/devices/platform/some_device_name", .subsystem = "tty",
- };
- std::vector<std::string> expected_result;
-
- DeviceHandlerTester device_handler_tester_;
- device_handler_tester_.TestGetSymlinks(platform_device, uevent, expected_result, false);
-}
-
-TEST(device_handler, get_character_device_symlinks_no_usb_found) {
- const char* platform_device = "/devices/platform/some_device_name";
- Uevent uevent = {
- .path = "/devices/platform/some_device_name/bad/bad/", .subsystem = "tty",
- };
- std::vector<std::string> expected_result;
-
- DeviceHandlerTester device_handler_tester_;
- device_handler_tester_.TestGetSymlinks(platform_device, uevent, expected_result, false);
-}
-
-TEST(device_handler, get_character_device_symlinks_no_roothub) {
- const char* platform_device = "/devices/platform/some_device_name";
- Uevent uevent = {
- .path = "/devices/platform/some_device_name/usb/", .subsystem = "tty",
- };
- std::vector<std::string> expected_result;
-
- DeviceHandlerTester device_handler_tester_;
- device_handler_tester_.TestGetSymlinks(platform_device, uevent, expected_result, false);
-}
-
-TEST(device_handler, get_character_device_symlinks_no_usb_device) {
- const char* platform_device = "/devices/platform/some_device_name";
- Uevent uevent = {
- .path = "/devices/platform/some_device_name/usb/usb_device/", .subsystem = "tty",
- };
- std::vector<std::string> expected_result;
-
- DeviceHandlerTester device_handler_tester_;
- device_handler_tester_.TestGetSymlinks(platform_device, uevent, expected_result, false);
-}
-
-TEST(device_handler, get_character_device_symlinks_no_final_slash) {
- const char* platform_device = "/devices/platform/some_device_name";
- Uevent uevent = {
- .path = "/devices/platform/some_device_name/usb/usb_device/name", .subsystem = "tty",
- };
- std::vector<std::string> expected_result;
-
- DeviceHandlerTester device_handler_tester_;
- device_handler_tester_.TestGetSymlinks(platform_device, uevent, expected_result, false);
-}
-
-TEST(device_handler, get_character_device_symlinks_no_final_name) {
- const char* platform_device = "/devices/platform/some_device_name";
- Uevent uevent = {
- .path = "/devices/platform/some_device_name/usb/usb_device//", .subsystem = "tty",
- };
- std::vector<std::string> expected_result;
-
- DeviceHandlerTester device_handler_tester_;
- device_handler_tester_.TestGetSymlinks(platform_device, uevent, expected_result, false);
-}
-
TEST(device_handler, get_block_device_symlinks_success_platform) {
// These are actual paths from bullhead
const char* platform_device = "/devices/soc.0/f9824900.sdhci";
@@ -164,7 +71,7 @@
std::vector<std::string> expected_result{"/dev/block/platform/soc.0/f9824900.sdhci/mmcblk0"};
DeviceHandlerTester device_handler_tester_;
- device_handler_tester_.TestGetSymlinks(platform_device, uevent, expected_result, true);
+ device_handler_tester_.TestGetSymlinks(platform_device, uevent, expected_result);
}
TEST(device_handler, get_block_device_symlinks_success_platform_with_partition) {
@@ -182,7 +89,7 @@
};
DeviceHandlerTester device_handler_tester_;
- device_handler_tester_.TestGetSymlinks(platform_device, uevent, expected_result, true);
+ device_handler_tester_.TestGetSymlinks(platform_device, uevent, expected_result);
}
TEST(device_handler, get_block_device_symlinks_success_platform_with_partition_only_num) {
@@ -198,7 +105,7 @@
};
DeviceHandlerTester device_handler_tester_;
- device_handler_tester_.TestGetSymlinks(platform_device, uevent, expected_result, true);
+ device_handler_tester_.TestGetSymlinks(platform_device, uevent, expected_result);
}
TEST(device_handler, get_block_device_symlinks_success_platform_with_partition_only_name) {
@@ -214,7 +121,7 @@
};
DeviceHandlerTester device_handler_tester_;
- device_handler_tester_.TestGetSymlinks(platform_device, uevent, expected_result, true);
+ device_handler_tester_.TestGetSymlinks(platform_device, uevent, expected_result);
}
TEST(device_handler, get_block_device_symlinks_success_pci) {
@@ -225,7 +132,7 @@
std::vector<std::string> expected_result{"/dev/block/pci/pci0000:00/0000:00:1f.2/mmcblk0"};
DeviceHandlerTester device_handler_tester_;
- device_handler_tester_.TestGetSymlinks(platform_device, uevent, expected_result, true);
+ device_handler_tester_.TestGetSymlinks(platform_device, uevent, expected_result);
}
TEST(device_handler, get_block_device_symlinks_pci_bad_format) {
@@ -236,7 +143,7 @@
std::vector<std::string> expected_result{};
DeviceHandlerTester device_handler_tester_;
- device_handler_tester_.TestGetSymlinks(platform_device, uevent, expected_result, true);
+ device_handler_tester_.TestGetSymlinks(platform_device, uevent, expected_result);
}
TEST(device_handler, get_block_device_symlinks_success_vbd) {
@@ -247,7 +154,7 @@
std::vector<std::string> expected_result{"/dev/block/vbd/1234/mmcblk0"};
DeviceHandlerTester device_handler_tester_;
- device_handler_tester_.TestGetSymlinks(platform_device, uevent, expected_result, true);
+ device_handler_tester_.TestGetSymlinks(platform_device, uevent, expected_result);
}
TEST(device_handler, get_block_device_symlinks_vbd_bad_format) {
@@ -258,7 +165,7 @@
std::vector<std::string> expected_result{};
DeviceHandlerTester device_handler_tester_;
- device_handler_tester_.TestGetSymlinks(platform_device, uevent, expected_result, true);
+ device_handler_tester_.TestGetSymlinks(platform_device, uevent, expected_result);
}
TEST(device_handler, get_block_device_symlinks_no_matches) {
@@ -271,7 +178,7 @@
std::vector<std::string> expected_result;
DeviceHandlerTester device_handler_tester_;
- device_handler_tester_.TestGetSymlinks(platform_device, uevent, expected_result, true);
+ device_handler_tester_.TestGetSymlinks(platform_device, uevent, expected_result);
}
TEST(device_handler, sanitize_null) {
diff --git a/init/init.cpp b/init/init.cpp
index 0562dad..d23e1a3 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -94,6 +94,7 @@
static std::unique_ptr<Timer> waiting_for_prop(nullptr);
static std::string wait_prop_name;
static std::string wait_prop_value;
+static bool shutting_down;
void DumpState() {
ServiceManager::GetInstance().DumpState();
@@ -158,21 +159,31 @@
return true;
}
+void ResetWaitForProp() {
+ wait_prop_name.clear();
+ wait_prop_value.clear();
+ waiting_for_prop.reset();
+}
+
void property_changed(const std::string& name, const std::string& value) {
// If the property is sys.powerctl, we bypass the event queue and immediately handle it.
// This is to ensure that init will always and immediately shutdown/reboot, regardless of
// if there are other pending events to process or if init is waiting on an exec service or
// waiting on a property.
- if (name == "sys.powerctl") HandlePowerctlMessage(value);
+ // In non-thermal-shutdown case, 'shutdown' trigger will be fired to let device specific
+ // commands to be executed.
+ if (name == "sys.powerctl") {
+ if (HandlePowerctlMessage(value)) {
+ shutting_down = true;
+ }
+ }
if (property_triggers_enabled) ActionManager::GetInstance().QueuePropertyChange(name, value);
if (waiting_for_prop) {
if (wait_prop_name == name && wait_prop_value == value) {
- wait_prop_name.clear();
- wait_prop_value.clear();
LOG(INFO) << "Wait for property took " << *waiting_for_prop;
- waiting_for_prop.reset();
+ ResetWaitForProp();
}
}
}
@@ -1135,7 +1146,7 @@
am.ExecuteOneCommand();
}
if (!(waiting_for_prop || sm.IsWaitingForExec())) {
- restart_processes();
+ if (!shutting_down) restart_processes();
// If there's a process that needs restarting, wake up in time for that.
if (process_needs_restart_at != 0) {
diff --git a/init/init.h b/init/init.h
index 479b771..aaab523 100644
--- a/init/init.h
+++ b/init/init.h
@@ -44,6 +44,8 @@
void DumpState();
+void ResetWaitForProp();
+
} // namespace init
} // namespace android
diff --git a/init/reboot.cpp b/init/reboot.cpp
index 34c98a7..ec1ddd6 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -49,6 +49,7 @@
#include <private/android_filesystem_config.h>
#include "capabilities.h"
+#include "init.h"
#include "property_service.h"
#include "service.h"
@@ -490,6 +491,9 @@
}
} else if (command == "thermal-shutdown") { // no additional parameter allowed
cmd = ANDROID_RB_THERMOFF;
+ // Do not queue "shutdown" trigger since we want to shutdown immediately
+ DoReboot(cmd, command, reboot_target, run_fsck);
+ return true;
} else {
command_invalid = true;
}
@@ -498,7 +502,26 @@
return false;
}
- DoReboot(cmd, command, reboot_target, run_fsck);
+ LOG(INFO) << "Clear action queue and start shutdown trigger";
+ ActionManager::GetInstance().ClearQueue();
+ // Queue shutdown trigger first
+ ActionManager::GetInstance().QueueEventTrigger("shutdown");
+ // Queue built-in shutdown_done
+ auto shutdown_handler = [cmd, command, reboot_target,
+ run_fsck](const std::vector<std::string>&) {
+ DoReboot(cmd, command, reboot_target, run_fsck);
+ return 0;
+ };
+ ActionManager::GetInstance().QueueBuiltinAction(shutdown_handler, "shutdown_done");
+
+ // Skip wait for prop if it is in progress
+ ResetWaitForProp();
+
+ // Skip wait for exec if it is in progress
+ if (ServiceManager::GetInstance().IsWaitingForExec()) {
+ ServiceManager::GetInstance().ClearExecWait();
+ }
+
return true;
}
diff --git a/init/service.cpp b/init/service.cpp
index f2e5d22..a2c4b50 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -34,6 +34,7 @@
#include <android-base/logging.h>
#include <android-base/parseint.h>
#include <android-base/properties.h>
+#include <android-base/scopeguard.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <processgroup/processgroup.h>
@@ -47,6 +48,7 @@
using android::base::boot_clock;
using android::base::GetProperty;
using android::base::Join;
+using android::base::make_scope_guard;
using android::base::ParseInt;
using android::base::StartsWith;
using android::base::StringPrintf;
@@ -1088,14 +1090,24 @@
}
bool ServiceManager::ReapOneProcess() {
- int status;
- pid_t pid = TEMP_FAILURE_RETRY(waitpid(-1, &status, WNOHANG));
- if (pid == 0) {
+ siginfo_t siginfo = {};
+ // This returns a zombie pid or informs us that there are no zombies left to be reaped.
+ // It does NOT reap the pid; that is done below.
+ if (TEMP_FAILURE_RETRY(waitid(P_ALL, 0, &siginfo, WEXITED | WNOHANG | WNOWAIT)) != 0) {
+ PLOG(ERROR) << "waitid failed";
return false;
- } else if (pid == -1) {
- PLOG(ERROR) << "waitpid failed";
- return false;
- } else if (PropertyChildReap(pid)) {
+ }
+
+ auto pid = siginfo.si_pid;
+ if (pid == 0) return false;
+
+ // At this point we know we have a zombie pid, so we use this scopeguard to reap the pid
+ // whenever the function returns from this point forward.
+ // We do NOT want to reap the zombie earlier as in Service::Reap(), we kill(-pid, ...) and we
+ // want the pid to remain valid throughout that (and potentially future) usages.
+ auto reaper = make_scope_guard([pid] { TEMP_FAILURE_RETRY(waitpid(pid, nullptr, WNOHANG)); });
+
+ if (PropertyChildReap(pid)) {
return true;
}
@@ -1112,14 +1124,11 @@
name = StringPrintf("Untracked pid %d", pid);
}
+ auto status = siginfo.si_status;
if (WIFEXITED(status)) {
LOG(INFO) << name << " exited with status " << WEXITSTATUS(status) << wait_string;
} else if (WIFSIGNALED(status)) {
LOG(INFO) << name << " killed by signal " << WTERMSIG(status) << wait_string;
- } else if (WIFSTOPPED(status)) {
- LOG(INFO) << name << " stopped by signal " << WSTOPSIG(status) << wait_string;
- } else {
- LOG(INFO) << name << " state changed" << wait_string;
}
if (!svc) {
@@ -1143,6 +1152,15 @@
}
}
+void ServiceManager::ClearExecWait() {
+ // Clear EXEC flag if there is one pending
+ // And clear the wait flag
+ for (const auto& s : services_) {
+ s->UnSetExec();
+ }
+ exec_waiter_.reset();
+}
+
bool ServiceParser::ParseSection(std::vector<std::string>&& args, const std::string& filename,
int line, std::string* err) {
if (args.size() < 3) {
diff --git a/init/service.h b/init/service.h
index 3c7dc74..0cc1683 100644
--- a/init/service.h
+++ b/init/service.h
@@ -89,6 +89,7 @@
void DumpState() const;
void SetShutdownCritical() { flags_ |= SVC_SHUTDOWN_CRITICAL; }
bool IsShutdownCritical() const { return (flags_ & SVC_SHUTDOWN_CRITICAL) != 0; }
+ void UnSetExec() { flags_ &= ~SVC_EXEC; }
const std::string& name() const { return name_; }
const std::set<std::string>& classnames() const { return classnames_; }
@@ -186,7 +187,7 @@
};
class ServiceManager {
-public:
+ public:
static ServiceManager& GetInstance();
// Exposed for testing
@@ -208,8 +209,9 @@
void ReapAnyOutstandingChildren();
void RemoveService(const Service& svc);
void DumpState() const;
+ void ClearExecWait();
-private:
+ private:
// Cleans up a child process that exited.
// Returns true iff a children was cleaned up.
bool ReapOneProcess();
diff --git a/init/util.cpp b/init/util.cpp
index 4b1894f..479179e 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -370,6 +370,7 @@
void panic() {
LOG(ERROR) << "panic: rebooting to bootloader";
+ // Do not queue "shutdown" trigger since we want to shutdown immediately
DoReboot(ANDROID_RB_RESTART2, "reboot", "bootloader", false);
}
diff --git a/rootdir/init.rc b/rootdir/init.rc
index ebbec35..ae86834 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -681,6 +681,10 @@
on property:security.perf_harden=1
write /proc/sys/kernel/perf_event_paranoid 3
+# on shutdown
+# In device's init.rc, this trigger can be used to do device-specific actions
+# before shutdown. e.g disable watchdog and mask error handling
+
## Daemon processes to be run by init.
##
service ueventd /sbin/ueventd