Merge "init: separate out epoll into a class"

am: c5fbf494e7

Change-Id: Ie92d8daa09eb60cf0a1a297a5546be54e7f9b2c3
This commit is contained in:
Tom Cherry 2018-05-22 08:09:06 -07:00 committed by android-build-merger
commit aaab7d69b5
9 changed files with 175 additions and 67 deletions

View file

@ -100,6 +100,7 @@ cc_library_static {
"capabilities.cpp", "capabilities.cpp",
"descriptors.cpp", "descriptors.cpp",
"devices.cpp", "devices.cpp",
"epoll.cpp",
"firmware_handler.cpp", "firmware_handler.cpp",
"import_parser.cpp", "import_parser.cpp",
"init.cpp", "init.cpp",

84
init/epoll.cpp Normal file
View file

@ -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

49
init/epoll.h Normal file
View file

@ -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

View file

@ -24,7 +24,6 @@
#include <signal.h> #include <signal.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/epoll.h>
#include <sys/mount.h> #include <sys/mount.h>
#include <sys/signalfd.h> #include <sys/signalfd.h>
#include <sys/sysmacros.h> #include <sys/sysmacros.h>
@ -48,6 +47,7 @@
#include <selinux/android.h> #include <selinux/android.h>
#include "action_parser.h" #include "action_parser.h"
#include "epoll.h"
#include "import_parser.h" #include "import_parser.h"
#include "init_first_stage.h" #include "init_first_stage.h"
#include "keychords.h" #include "keychords.h"
@ -61,6 +61,7 @@
#include "util.h" #include "util.h"
#include "watchdogd.h" #include "watchdogd.h"
using namespace std::chrono_literals;
using namespace std::string_literals; using namespace std::string_literals;
using android::base::boot_clock; using android::base::boot_clock;
@ -79,7 +80,6 @@ static char qemu[32];
std::string default_console = "/dev/console"; std::string default_console = "/dev/console";
static int epoll_fd = -1;
static int signal_fd = -1; static int signal_fd = -1;
static std::unique_ptr<Timer> waiting_for_prop(nullptr); static std::unique_ptr<Timer> waiting_for_prop(nullptr);
@ -131,34 +131,6 @@ static void LoadBootScripts(ActionManager& action_manager, ServiceList& service_
} }
} }
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) bool start_waiting_for_property(const char *name, const char *value)
{ {
if (waiting_for_prop) { if (waiting_for_prop) {
@ -343,11 +315,6 @@ static Result<Success> wait_for_coldboot_done_action(const BuiltinArguments& arg
return Success(); return Success();
} }
static Result<Success> KeychordInitAction(const BuiltinArguments& args) {
KeychordInit();
return Success();
}
static Result<Success> console_init_action(const BuiltinArguments& args) { static Result<Success> console_init_action(const BuiltinArguments& args) {
std::string console = GetProperty("ro.boot.console", ""); std::string console = GetProperty("ro.boot.console", "");
if (!console.empty()) { if (!console.empty()) {
@ -550,7 +517,7 @@ static void UnblockSignals() {
} }
} }
static void InstallSignalFdHandler() { static void InstallSignalFdHandler(Epoll* epoll) {
// Applying SA_NOCLDSTOP to a defaulted SIGCHLD handler prevents the signalfd from receiving // Applying SA_NOCLDSTOP to a defaulted SIGCHLD handler prevents the signalfd from receiving
// SIGCHLD when a child process stops or continues (b/77867680#comment9). // SIGCHLD when a child process stops or continues (b/77867680#comment9).
const struct sigaction act { .sa_handler = SIG_DFL, .sa_flags = SA_NOCLDSTOP }; const struct sigaction act { .sa_handler = SIG_DFL, .sa_flags = SA_NOCLDSTOP };
@ -581,7 +548,9 @@ static void InstallSignalFdHandler() {
PLOG(FATAL) << "failed to create signalfd"; 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) { int main(int argc, char** argv) {
@ -727,16 +696,16 @@ int main(int argc, char** argv) {
SelabelInitialize(); SelabelInitialize();
SelinuxRestoreContext(); SelinuxRestoreContext();
epoll_fd = epoll_create1(EPOLL_CLOEXEC); Epoll epoll;
if (epoll_fd == -1) { if (auto result = epoll.Open(); !result) {
PLOG(FATAL) << "epoll_create1 failed"; PLOG(FATAL) << result.error();
} }
InstallSignalFdHandler(); InstallSignalFdHandler(&epoll);
property_load_boot_defaults(); property_load_boot_defaults();
export_oem_lock_status(); export_oem_lock_status();
start_property_service(); StartPropertyService(&epoll);
set_usb_controller(); set_usb_controller();
const BuiltinFunctionMap function_map; const BuiltinFunctionMap function_map;
@ -761,7 +730,12 @@ int main(int argc, char** argv) {
am.QueueBuiltinAction(MixHwrngIntoLinuxRngAction, "MixHwrngIntoLinuxRng"); am.QueueBuiltinAction(MixHwrngIntoLinuxRngAction, "MixHwrngIntoLinuxRng");
am.QueueBuiltinAction(SetMmapRndBitsAction, "SetMmapRndBits"); am.QueueBuiltinAction(SetMmapRndBitsAction, "SetMmapRndBits");
am.QueueBuiltinAction(SetKptrRestrictAction, "SetKptrRestrict"); 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"); am.QueueBuiltinAction(console_init_action, "console_init");
// Trigger all the boot actions to get us started. // Trigger all the boot actions to get us started.
@ -784,7 +758,7 @@ int main(int argc, char** argv) {
while (true) { while (true) {
// By default, sleep until something happens. // By default, sleep until something happens.
int epoll_timeout_ms = -1; auto epoll_timeout = std::optional<std::chrono::milliseconds>{};
if (do_shutdown && !shutting_down) { if (do_shutdown && !shutting_down) {
do_shutdown = false; do_shutdown = false;
@ -802,23 +776,18 @@ int main(int argc, char** argv) {
// If there's a process that needs restarting, wake up in time for that. // If there's a process that needs restarting, wake up in time for that.
if (next_process_restart_time) { if (next_process_restart_time) {
epoll_timeout_ms = std::chrono::ceil<std::chrono::milliseconds>( epoll_timeout = std::chrono::ceil<std::chrono::milliseconds>(
*next_process_restart_time - boot_clock::now()) *next_process_restart_time - boot_clock::now());
.count(); if (*epoll_timeout < 0ms) epoll_timeout = 0ms;
if (epoll_timeout_ms < 0) epoll_timeout_ms = 0;
} }
} }
// If there's more work to do, wake up again immediately. // 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; if (auto result = epoll.Wait(epoll_timeout); !result) {
int nr = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd, &ev, 1, epoll_timeout_ms)); LOG(ERROR) << result.error();
if (nr == -1) {
PLOG(ERROR) << "epoll_wait failed";
} else if (nr == 1) {
std::invoke(*reinterpret_cast<std::function<void()>*>(ev.data.ptr));
} }
} }

View file

@ -43,9 +43,6 @@ void HandleControlMessage(const std::string& msg, const std::string& arg, pid_t
void property_changed(const std::string& name, const std::string& value); 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); bool start_waiting_for_property(const char *name, const char *value);
void DumpState(); void DumpState();

View file

@ -36,6 +36,7 @@
#include <android-base/properties.h> #include <android-base/properties.h>
#include "init.h" #include "init.h"
#include "service.h"
namespace android { namespace android {
namespace init { namespace init {
@ -43,6 +44,7 @@ namespace init {
namespace { namespace {
int keychords_count; int keychords_count;
Epoll* epoll;
struct KeychordEntry { struct KeychordEntry {
const std::vector<int> keycodes; const std::vector<int> keycodes;
@ -214,7 +216,7 @@ bool KeychordGeteventEnable(int fd) {
keychord_current |= mask & available & set; keychord_current |= mask & available & set;
KeychordLambdaCheck(); KeychordLambdaCheck();
} }
register_epoll_handler(fd, [fd]() { KeychordLambdaHandler(fd); }); epoll->RegisterHandler(fd, [fd]() { KeychordLambdaHandler(fd); });
return true; return true;
} }
@ -236,7 +238,7 @@ void GeteventCloseDevice(const std::string& device) {
auto it = keychord_registration.find(device); auto it = keychord_registration.find(device);
if (it == keychord_registration.end()) return; if (it == keychord_registration.end()) return;
auto fd = (*it).second; auto fd = (*it).second;
unregister_epoll_handler(fd); epoll->UnregisterHandler(fd);
keychord_registration.erase(it); keychord_registration.erase(it);
::close(fd); ::close(fd);
} }
@ -294,7 +296,7 @@ void GeteventOpenDevice() {
} }
} }
if (inotify_fd >= 0) register_epoll_handler(inotify_fd, InotifyHandler); if (inotify_fd >= 0) epoll->RegisterHandler(inotify_fd, InotifyHandler);
} }
void AddServiceKeycodes(Service* svc) { void AddServiceKeycodes(Service* svc) {
@ -309,7 +311,8 @@ void AddServiceKeycodes(Service* svc) {
} // namespace } // namespace
void KeychordInit() { void KeychordInit(Epoll* init_epoll) {
epoll = init_epoll;
for (const auto& service : ServiceList::GetInstance()) { for (const auto& service : ServiceList::GetInstance()) {
AddServiceKeycodes(service.get()); AddServiceKeycodes(service.get());
} }

View file

@ -17,12 +17,12 @@
#ifndef _INIT_KEYCHORDS_H_ #ifndef _INIT_KEYCHORDS_H_
#define _INIT_KEYCHORDS_H_ #define _INIT_KEYCHORDS_H_
#include "service.h" #include "epoll.h"
namespace android { namespace android {
namespace init { namespace init {
void KeychordInit(); void KeychordInit(Epoll* init_epoll);
} // namespace init } // namespace init
} // namespace android } // namespace android

View file

@ -56,6 +56,7 @@
#include <selinux/label.h> #include <selinux/label.h>
#include <selinux/selinux.h> #include <selinux/selinux.h>
#include "epoll.h"
#include "init.h" #include "init.h"
#include "persistent_properties.h" #include "persistent_properties.h"
#include "property_type.h" #include "property_type.h"
@ -808,7 +809,7 @@ void CreateSerializedPropertyInfo() {
selinux_android_restorecon(kPropertyInfosPath, 0); selinux_android_restorecon(kPropertyInfosPath, 0);
} }
void start_property_service() { void StartPropertyService(Epoll* epoll) {
selinux_callback cb; selinux_callback cb;
cb.func_audit = SelinuxAuditCallback; cb.func_audit = SelinuxAuditCallback;
selinux_set_callback(SELINUX_CB_AUDIT, cb); selinux_set_callback(SELINUX_CB_AUDIT, cb);
@ -823,7 +824,9 @@ void start_property_service() {
listen(property_set_fd, 8); 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 } // namespace init

View file

@ -21,6 +21,8 @@
#include <string> #include <string>
#include "epoll.h"
namespace android { namespace android {
namespace init { namespace init {
@ -40,7 +42,7 @@ void property_init(void);
void property_load_boot_defaults(void); void property_load_boot_defaults(void);
void load_persist_props(void); void load_persist_props(void);
void load_system_props(void); void load_system_props(void);
void start_property_service(void); void StartPropertyService(Epoll* epoll);
} // namespace init } // namespace init
} // namespace android } // namespace android