Merge "init: Handle properties in the background of calling fs_mgr"
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 44cac4b..d9b1b85 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -588,7 +588,12 @@
     if (!ReadFstabFromFile(fstab_file, &fstab)) {
         return Error() << "Could not read fstab";
     }
-    auto mount_fstab_return_code = fs_mgr_mount_all(&fstab, mount_mode);
+
+    auto mount_fstab_return_code =
+            CallFunctionAndHandleProperties(fs_mgr_mount_all, &fstab, mount_mode);
+    if (!mount_fstab_return_code) {
+        return Error() << "Could not call fs_mgr_mount_all(): " << mount_fstab_return_code.error();
+    }
     property_set(prop_name, std::to_string(t.duration().count()));
 
     if (import_rc && SelinuxGetVendorAndroidVersion() <= __ANDROID_API_Q__) {
@@ -599,7 +604,7 @@
     if (queue_event) {
         /* queue_fs_event will queue event based on mount_fstab return code
          * and return processed return code*/
-        auto queue_fs_result = queue_fs_event(mount_fstab_return_code);
+        auto queue_fs_result = queue_fs_event(*mount_fstab_return_code);
         if (!queue_fs_result) {
             return Error() << "queue_fs_event() failed: " << queue_fs_result.error();
         }
@@ -615,8 +620,13 @@
         return Error() << "Could not read fstab";
     }
 
-    if (auto result = fs_mgr_umount_all(&fstab); result != 0) {
-        return Error() << "umount_fstab() failed " << result;
+    auto result = CallFunctionAndHandleProperties(fs_mgr_umount_all, &fstab);
+    if (!result) {
+        return Error() << "Could not call fs_mgr_mount_all() " << result.error();
+    }
+
+    if (*result != 0) {
+        return Error() << "fs_mgr_mount_all() failed: " << *result;
     }
     return {};
 }
@@ -627,8 +637,13 @@
         return Error() << "Could not read fstab '" << args[1] << "'";
     }
 
-    if (!fs_mgr_swapon_all(fstab)) {
-        return Error() << "fs_mgr_swapon_all() failed";
+    auto result = CallFunctionAndHandleProperties(fs_mgr_swapon_all, fstab);
+    if (!result) {
+        return Error() << "Could not call fs_mgr_swapon_all() " << result.error();
+    }
+
+    if (*result == 0) {
+        return Error() << "fs_mgr_swapon_all() failed.";
     }
 
     return {};
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 14bb819..1520c9f 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -39,6 +39,7 @@
 #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
 #include <sys/_system_properties.h>
 
+#include <atomic>
 #include <map>
 #include <memory>
 #include <mutex>
@@ -52,6 +53,7 @@
 #include <android-base/properties.h>
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
+#include <android-base/unique_fd.h>
 #include <property_info_parser/property_info_parser.h>
 #include <property_info_serializer/property_info_serializer.h>
 #include <selinux/android.h>
@@ -59,7 +61,6 @@
 #include <selinux/selinux.h>
 
 #include "debug_ramdisk.h"
-#include "epoll.h"
 #include "init.h"
 #include "persistent_properties.h"
 #include "property_type.h"
@@ -76,6 +77,7 @@
 using android::base::StringPrintf;
 using android::base::Timer;
 using android::base::Trim;
+using android::base::unique_fd;
 using android::base::WriteStringToFile;
 using android::properties::BuildTrie;
 using android::properties::ParsePropertyInfoFile;
@@ -1006,5 +1008,42 @@
     }
 }
 
+Result<int> CallFunctionAndHandlePropertiesImpl(const std::function<int()>& f) {
+    unique_fd reader;
+    unique_fd writer;
+    if (!Socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, &reader, &writer)) {
+        return ErrnoError() << "Could not create socket pair";
+    }
+
+    int result = 0;
+    std::atomic<bool> end = false;
+    auto thread = std::thread{[&f, &result, &end, &writer] {
+        result = f();
+        end = true;
+        send(writer, "1", 1, 0);
+    }};
+
+    Epoll epoll;
+    if (auto result = epoll.Open(); !result) {
+        return Error() << "Could not create epoll: " << result.error();
+    }
+    if (auto result = epoll.RegisterHandler(property_set_fd, handle_property_set_fd); !result) {
+        return Error() << "Could not register epoll handler for property fd: " << result.error();
+    }
+
+    // No-op function, just used to break from loop.
+    if (auto result = epoll.RegisterHandler(reader, [] {}); !result) {
+        return Error() << "Could not register epoll handler for ending thread:" << result.error();
+    }
+
+    while (!end) {
+        epoll.Wait({});
+    }
+
+    thread.join();
+
+    return result;
+}
+
 }  // namespace init
 }  // namespace android
diff --git a/init/property_service.h b/init/property_service.h
index 7f9f844..dc47b4d 100644
--- a/init/property_service.h
+++ b/init/property_service.h
@@ -18,9 +18,11 @@
 
 #include <sys/socket.h>
 
+#include <functional>
 #include <string>
 
 #include "epoll.h"
+#include "result.h"
 
 namespace android {
 namespace init {
@@ -37,5 +39,13 @@
 void load_persist_props();
 void StartPropertyService(Epoll* epoll);
 
+template <typename F, typename... Args>
+Result<int> CallFunctionAndHandleProperties(F&& f, Args&&... args) {
+    Result<int> CallFunctionAndHandlePropertiesImpl(const std::function<int()>& f);
+
+    auto func = [&] { return f(args...); };
+    return CallFunctionAndHandlePropertiesImpl(func);
+}
+
 }  // namespace init
 }  // namespace android