init: run property service in a thread
It's been a long standing issue that init cannot respond to property
set messages when it is running a builtin command. This is
particularly problematic when the commands involve IPC to vold or
other daemons, as it prevents them from being able to set properties.
This change has init run property service in a thread, which
eliminates the above issue.
This change may also serve as a starting block to running property
service in an entirely different process to better isolate init from
handling property requests.
Test: CF boots, walleye boots, properties are set appropriately
Change-Id: Id9534a5916abb2f7d2a49cda54e33c1b69c50c2f
diff --git a/init/init.cpp b/init/init.cpp
index 18fb0c3..e8eb571 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -61,6 +61,7 @@
#include "mount_handler.h"
#include "mount_namespace.h"
#include "property_service.h"
+#include "proto_utils.h"
#include "reboot.h"
#include "reboot_utils.h"
#include "security.h"
@@ -69,6 +70,7 @@
#include "service.h"
#include "service_parser.h"
#include "sigchld_handler.h"
+#include "system/core/init/property_service.pb.h"
#include "util.h"
using namespace std::chrono_literals;
@@ -90,6 +92,7 @@
static char qemu[32];
static int signal_fd = -1;
+static int property_fd = -1;
static std::unique_ptr<Timer> waiting_for_prop(nullptr);
static std::string wait_prop_name;
@@ -613,6 +616,54 @@
selinux_start_time_ns));
}
+void SendLoadPersistentPropertiesMessage() {
+ auto init_message = InitMessage{};
+ init_message.set_load_persistent_properties(true);
+ if (auto result = SendMessage(property_fd, init_message); !result) {
+ LOG(ERROR) << "Failed to send load persistent properties message: " << result.error();
+ }
+}
+
+static void HandlePropertyFd() {
+ auto message = ReadMessage(property_fd);
+ if (!message) {
+ LOG(ERROR) << "Could not read message from property service: " << message.error();
+ return;
+ }
+
+ auto property_message = PropertyMessage{};
+ if (!property_message.ParseFromString(*message)) {
+ LOG(ERROR) << "Could not parse message from property service";
+ return;
+ }
+
+ switch (property_message.msg_case()) {
+ case PropertyMessage::kControlMessage: {
+ auto& control_message = property_message.control_message();
+ bool response = HandleControlMessage(control_message.msg(), control_message.name(),
+ control_message.pid());
+
+ auto init_message = InitMessage{};
+ auto* control_response = init_message.mutable_control_response();
+
+ control_response->set_result(response);
+
+ if (auto result = SendMessage(property_fd, init_message); !result) {
+ LOG(ERROR) << "Failed to send control response: " << result.error();
+ }
+ break;
+ }
+ case PropertyMessage::kChangedMessage: {
+ auto& changed_message = property_message.changed_message();
+ property_changed(changed_message.name(), changed_message.value());
+ break;
+ }
+ default:
+ LOG(ERROR) << "Unknown message type from property service: "
+ << property_message.msg_case();
+ }
+}
+
int SecondStageMain(int argc, char** argv) {
if (REBOOT_BOOTLOADER_ON_PANIC) {
InstallRebootSignalHandlers();
@@ -684,7 +735,12 @@
UmountDebugRamdisk();
fs_mgr_vendor_overlay_mount_all();
export_oem_lock_status();
- StartPropertyService(&epoll);
+
+ StartPropertyService(&property_fd);
+ if (auto result = epoll.RegisterHandler(property_fd, HandlePropertyFd); !result) {
+ LOG(FATAL) << "Could not register epoll handler for property fd: " << result.error();
+ }
+
MountHandler mount_handler(&epoll);
set_usb_controller();