Merge "fastboot: better temporary file errors."
diff --git a/init/Android.bp b/init/Android.bp
index a31c5a5..63f3fca 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -100,6 +100,7 @@
         "capabilities.cpp",
         "descriptors.cpp",
         "devices.cpp",
+        "epoll.cpp",
         "firmware_handler.cpp",
         "import_parser.cpp",
         "init.cpp",
diff --git a/init/epoll.cpp b/init/epoll.cpp
new file mode 100644
index 0000000..4bca09e
--- /dev/null
+++ b/init/epoll.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "epoll.h"
+
+#include <sys/epoll.h>
+
+#include <chrono>
+#include <functional>
+#include <map>
+
+namespace android {
+namespace init {
+
+Epoll::Epoll() {}
+
+Result<Success> Epoll::Open() {
+    if (epoll_fd_ >= 0) return Success();
+    epoll_fd_.reset(epoll_create1(EPOLL_CLOEXEC));
+
+    if (epoll_fd_ == -1) {
+        return ErrnoError() << "epoll_create1 failed";
+    }
+    return Success();
+}
+
+Result<Success> Epoll::RegisterHandler(int fd, std::function<void()> handler) {
+    auto [it, inserted] = epoll_handlers_.emplace(fd, std::move(handler));
+    if (!inserted) {
+        return Error() << "Cannot specify two epoll handlers for a given FD";
+    }
+    epoll_event ev;
+    ev.events = EPOLLIN;
+    // std::map's iterators do not get invalidated until erased, so we use the
+    // pointer to the std::function in the map directly for epoll_ctl.
+    ev.data.ptr = reinterpret_cast<void*>(&it->second);
+    if (epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, fd, &ev) == -1) {
+        Result<Success> result = ErrnoError() << "epoll_ctl failed to add fd";
+        epoll_handlers_.erase(fd);
+        return result;
+    }
+    return Success();
+}
+
+Result<Success> Epoll::UnregisterHandler(int fd) {
+    if (epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, fd, nullptr) == -1) {
+        return ErrnoError() << "epoll_ctl failed to remove fd";
+    }
+    if (epoll_handlers_.erase(fd) != 1) {
+        return Error() << "Attempting to remove epoll handler for FD without an existing handler";
+    }
+    return Success();
+}
+
+Result<Success> Epoll::Wait(std::optional<std::chrono::milliseconds> timeout) {
+    int timeout_ms = -1;
+    if (timeout && timeout->count() < INT_MAX) {
+        timeout_ms = timeout->count();
+    }
+    epoll_event ev;
+    auto nr = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd_, &ev, 1, timeout_ms));
+    if (nr == -1) {
+        return ErrnoError() << "epoll_wait failed";
+    } else if (nr == 1) {
+        std::invoke(*reinterpret_cast<std::function<void()>*>(ev.data.ptr));
+    }
+    return Success();
+}
+
+}  // namespace init
+}  // namespace android
diff --git a/init/epoll.h b/init/epoll.h
new file mode 100644
index 0000000..85a791c
--- /dev/null
+++ b/init/epoll.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _INIT_EPOLL_H
+#define _INIT_EPOLL_H
+
+#include <chrono>
+#include <functional>
+#include <map>
+#include <optional>
+
+#include <android-base/unique_fd.h>
+
+#include "result.h"
+
+namespace android {
+namespace init {
+
+class Epoll {
+  public:
+    Epoll();
+
+    Result<Success> Open();
+    Result<Success> RegisterHandler(int fd, std::function<void()> handler);
+    Result<Success> UnregisterHandler(int fd);
+    Result<Success> Wait(std::optional<std::chrono::milliseconds> timeout);
+
+  private:
+    android::base::unique_fd epoll_fd_;
+    std::map<int, std::function<void()>> epoll_handlers_;
+};
+
+}  // namespace init
+}  // namespace android
+
+#endif
diff --git a/init/init.cpp b/init/init.cpp
index 645184b..fd9a90c 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -24,7 +24,6 @@
 #include <signal.h>
 #include <stdlib.h>
 #include <string.h>
-#include <sys/epoll.h>
 #include <sys/mount.h>
 #include <sys/signalfd.h>
 #include <sys/sysmacros.h>
@@ -48,6 +47,7 @@
 #include <selinux/android.h>
 
 #include "action_parser.h"
+#include "epoll.h"
 #include "import_parser.h"
 #include "init_first_stage.h"
 #include "keychords.h"
@@ -61,6 +61,7 @@
 #include "util.h"
 #include "watchdogd.h"
 
+using namespace std::chrono_literals;
 using namespace std::string_literals;
 
 using android::base::boot_clock;
@@ -79,7 +80,6 @@
 
 std::string default_console = "/dev/console";
 
-static int epoll_fd = -1;
 static int signal_fd = -1;
 
 static std::unique_ptr<Timer> waiting_for_prop(nullptr);
@@ -131,34 +131,6 @@
     }
 }
 
-static std::map<int, std::function<void()>> epoll_handlers;
-
-void register_epoll_handler(int fd, std::function<void()> handler) {
-    auto[it, inserted] = epoll_handlers.emplace(fd, std::move(handler));
-    if (!inserted) {
-        LOG(ERROR) << "Cannot specify two epoll handlers for a given FD";
-        return;
-    }
-    epoll_event ev;
-    ev.events = EPOLLIN;
-    // std::map's iterators do not get invalidated until erased, so we use the pointer to the
-    // std::function in the map directly for epoll_ctl.
-    ev.data.ptr = reinterpret_cast<void*>(&it->second);
-    if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ev) == -1) {
-        PLOG(ERROR) << "epoll_ctl failed to add fd";
-        epoll_handlers.erase(fd);
-    }
-}
-
-void unregister_epoll_handler(int fd) {
-    if (epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, nullptr) == -1) {
-        PLOG(ERROR) << "epoll_ctl failed to remove fd";
-    }
-    if (epoll_handlers.erase(fd) != 1) {
-        LOG(ERROR) << "Attempting to remove epoll handler for FD without an existing handler";
-    }
-}
-
 bool start_waiting_for_property(const char *name, const char *value)
 {
     if (waiting_for_prop) {
@@ -343,11 +315,6 @@
     return Success();
 }
 
-static Result<Success> KeychordInitAction(const BuiltinArguments& args) {
-    KeychordInit();
-    return Success();
-}
-
 static Result<Success> console_init_action(const BuiltinArguments& args) {
     std::string console = GetProperty("ro.boot.console", "");
     if (!console.empty()) {
@@ -550,7 +517,7 @@
     }
 }
 
-static void InstallSignalFdHandler() {
+static void InstallSignalFdHandler(Epoll* epoll) {
     // Applying SA_NOCLDSTOP to a defaulted SIGCHLD handler prevents the signalfd from receiving
     // SIGCHLD when a child process stops or continues (b/77867680#comment9).
     const struct sigaction act { .sa_handler = SIG_DFL, .sa_flags = SA_NOCLDSTOP };
@@ -581,7 +548,9 @@
         PLOG(FATAL) << "failed to create signalfd";
     }
 
-    register_epoll_handler(signal_fd, HandleSignalFd);
+    if (auto result = epoll->RegisterHandler(signal_fd, HandleSignalFd); !result) {
+        LOG(FATAL) << result.error();
+    }
 }
 
 int main(int argc, char** argv) {
@@ -727,16 +696,16 @@
     SelabelInitialize();
     SelinuxRestoreContext();
 
-    epoll_fd = epoll_create1(EPOLL_CLOEXEC);
-    if (epoll_fd == -1) {
-        PLOG(FATAL) << "epoll_create1 failed";
+    Epoll epoll;
+    if (auto result = epoll.Open(); !result) {
+        PLOG(FATAL) << result.error();
     }
 
-    InstallSignalFdHandler();
+    InstallSignalFdHandler(&epoll);
 
     property_load_boot_defaults();
     export_oem_lock_status();
-    start_property_service();
+    StartPropertyService(&epoll);
     set_usb_controller();
 
     const BuiltinFunctionMap function_map;
@@ -761,7 +730,12 @@
     am.QueueBuiltinAction(MixHwrngIntoLinuxRngAction, "MixHwrngIntoLinuxRng");
     am.QueueBuiltinAction(SetMmapRndBitsAction, "SetMmapRndBits");
     am.QueueBuiltinAction(SetKptrRestrictAction, "SetKptrRestrict");
-    am.QueueBuiltinAction(KeychordInitAction, "KeychordInit");
+    am.QueueBuiltinAction(
+        [&epoll](const BuiltinArguments& args) -> Result<Success> {
+            KeychordInit(&epoll);
+            return Success();
+        },
+        "KeychordInit");
     am.QueueBuiltinAction(console_init_action, "console_init");
 
     // Trigger all the boot actions to get us started.
@@ -784,7 +758,7 @@
 
     while (true) {
         // By default, sleep until something happens.
-        int epoll_timeout_ms = -1;
+        auto epoll_timeout = std::optional<std::chrono::milliseconds>{};
 
         if (do_shutdown && !shutting_down) {
             do_shutdown = false;
@@ -802,23 +776,18 @@
 
                 // If there's a process that needs restarting, wake up in time for that.
                 if (next_process_restart_time) {
-                    epoll_timeout_ms = std::chrono::ceil<std::chrono::milliseconds>(
-                                           *next_process_restart_time - boot_clock::now())
-                                           .count();
-                    if (epoll_timeout_ms < 0) epoll_timeout_ms = 0;
+                    epoll_timeout = std::chrono::ceil<std::chrono::milliseconds>(
+                        *next_process_restart_time - boot_clock::now());
+                    if (*epoll_timeout < 0ms) epoll_timeout = 0ms;
                 }
             }
 
             // If there's more work to do, wake up again immediately.
-            if (am.HasMoreCommands()) epoll_timeout_ms = 0;
+            if (am.HasMoreCommands()) epoll_timeout = 0ms;
         }
 
-        epoll_event ev;
-        int nr = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd, &ev, 1, epoll_timeout_ms));
-        if (nr == -1) {
-            PLOG(ERROR) << "epoll_wait failed";
-        } else if (nr == 1) {
-            std::invoke(*reinterpret_cast<std::function<void()>*>(ev.data.ptr));
+        if (auto result = epoll.Wait(epoll_timeout); !result) {
+            LOG(ERROR) << result.error();
         }
     }
 
diff --git a/init/init.h b/init/init.h
index e7c4d8d..6c82fa1 100644
--- a/init/init.h
+++ b/init/init.h
@@ -43,9 +43,6 @@
 
 void property_changed(const std::string& name, const std::string& value);
 
-void register_epoll_handler(int fd, std::function<void()> handler);
-void unregister_epoll_handler(int fd);
-
 bool start_waiting_for_property(const char *name, const char *value);
 
 void DumpState();
diff --git a/init/keychords.cpp b/init/keychords.cpp
index 293736d..418cdeb 100644
--- a/init/keychords.cpp
+++ b/init/keychords.cpp
@@ -36,6 +36,7 @@
 #include <android-base/properties.h>
 
 #include "init.h"
+#include "service.h"
 
 namespace android {
 namespace init {
@@ -43,6 +44,7 @@
 namespace {
 
 int keychords_count;
+Epoll* epoll;
 
 struct KeychordEntry {
     const std::vector<int> keycodes;
@@ -214,7 +216,7 @@
         keychord_current |= mask & available & set;
         KeychordLambdaCheck();
     }
-    register_epoll_handler(fd, [fd]() { KeychordLambdaHandler(fd); });
+    epoll->RegisterHandler(fd, [fd]() { KeychordLambdaHandler(fd); });
     return true;
 }
 
@@ -236,7 +238,7 @@
     auto it = keychord_registration.find(device);
     if (it == keychord_registration.end()) return;
     auto fd = (*it).second;
-    unregister_epoll_handler(fd);
+    epoll->UnregisterHandler(fd);
     keychord_registration.erase(it);
     ::close(fd);
 }
@@ -294,7 +296,7 @@
         }
     }
 
-    if (inotify_fd >= 0) register_epoll_handler(inotify_fd, InotifyHandler);
+    if (inotify_fd >= 0) epoll->RegisterHandler(inotify_fd, InotifyHandler);
 }
 
 void AddServiceKeycodes(Service* svc) {
@@ -309,7 +311,8 @@
 
 }  // namespace
 
-void KeychordInit() {
+void KeychordInit(Epoll* init_epoll) {
+    epoll = init_epoll;
     for (const auto& service : ServiceList::GetInstance()) {
         AddServiceKeycodes(service.get());
     }
diff --git a/init/keychords.h b/init/keychords.h
index 689a3b5..f3aecbb 100644
--- a/init/keychords.h
+++ b/init/keychords.h
@@ -17,12 +17,12 @@
 #ifndef _INIT_KEYCHORDS_H_
 #define _INIT_KEYCHORDS_H_
 
-#include "service.h"
+#include "epoll.h"
 
 namespace android {
 namespace init {
 
-void KeychordInit();
+void KeychordInit(Epoll* init_epoll);
 
 }  // namespace init
 }  // namespace android
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 47e45ef..741fde0 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -56,6 +56,7 @@
 #include <selinux/label.h>
 #include <selinux/selinux.h>
 
+#include "epoll.h"
 #include "init.h"
 #include "persistent_properties.h"
 #include "property_type.h"
@@ -371,6 +372,7 @@
 
             int result = TEMP_FAILURE_RETRY(recv(socket_, data, bytes_left, MSG_DONTWAIT));
             if (result <= 0) {
+                PLOG(ERROR) << "sys_prop: recv error";
                 return false;
             }
 
@@ -378,6 +380,10 @@
             data += result;
         }
 
+        if (bytes_left != 0) {
+            LOG(ERROR) << "sys_prop: recv data is not properly obtained.";
+        }
+
         return bytes_left == 0;
     }
 
@@ -808,7 +814,7 @@
     selinux_android_restorecon(kPropertyInfosPath, 0);
 }
 
-void start_property_service() {
+void StartPropertyService(Epoll* epoll) {
     selinux_callback cb;
     cb.func_audit = SelinuxAuditCallback;
     selinux_set_callback(SELINUX_CB_AUDIT, cb);
@@ -823,7 +829,9 @@
 
     listen(property_set_fd, 8);
 
-    register_epoll_handler(property_set_fd, handle_property_set_fd);
+    if (auto result = epoll->RegisterHandler(property_set_fd, handle_property_set_fd); !result) {
+        PLOG(FATAL) << result.error();
+    }
 }
 
 }  // namespace init
diff --git a/init/property_service.h b/init/property_service.h
index 29eaaa9..4a354c2 100644
--- a/init/property_service.h
+++ b/init/property_service.h
@@ -21,6 +21,8 @@
 
 #include <string>
 
+#include "epoll.h"
+
 namespace android {
 namespace init {
 
@@ -40,7 +42,7 @@
 void property_load_boot_defaults(void);
 void load_persist_props(void);
 void load_system_props(void);
-void start_property_service(void);
+void StartPropertyService(Epoll* epoll);
 
 }  // namespace init
 }  // namespace android