diff --git a/init/init.cpp b/init/init.cpp index 4ed23b6c0..90cbea0b6 100644 --- a/init/init.cpp +++ b/init/init.cpp @@ -25,8 +25,8 @@ #include #include #include +#include #include -#include #include #include #include @@ -82,6 +82,17 @@ static const char *ENV[32]; bool waiting_for_exec = false; +static int epoll_fd = -1; + +void register_epoll_handler(int fd, void (*fn)()) { + epoll_event ev; + ev.events = EPOLLIN; + ev.data.ptr = reinterpret_cast(fn); + if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ev) == -1) { + ERROR("epoll_ctl failed: %s\n", strerror(errno)); + } +} + void service::NotifyStateChange(const char* new_state) { if (!properties_initialized()) { // If properties aren't available yet, we can't set them. @@ -1037,7 +1048,13 @@ int main(int argc, char** argv) { restorecon("/dev/__properties__"); restorecon_recursive("/sys"); - signal_init(); + epoll_fd = epoll_create1(EPOLL_CLOEXEC); + if (epoll_fd == -1) { + ERROR("epoll_create1 failed: %s\n", strerror(errno)); + exit(1); + } + + signal_handler_init(); property_load_boot_defaults(); start_property_service(); @@ -1071,27 +1088,12 @@ int main(int argc, char** argv) { // Run all property triggers based on current state of the properties. queue_builtin_action(queue_property_triggers_action, "queue_property_triggers"); - size_t fd_count = 0; - struct pollfd ufds[3]; - ufds[fd_count++] = { .fd = get_signal_fd(), .events = POLLIN, .revents = 0 }; - ufds[fd_count++] = { .fd = get_property_set_fd(), .events = POLLIN, .revents = 0 }; - // TODO: can we work out when /dev/keychord is first accessible and open this fd then? - bool keychord_fd_init = false; - while (true) { if (!waiting_for_exec) { execute_one_command(); restart_processes(); } - if (!keychord_fd_init && get_keychord_fd() > 0) { - ufds[fd_count].fd = get_keychord_fd(); - ufds[fd_count].events = POLLIN; - ufds[fd_count].revents = 0; - fd_count++; - keychord_fd_init = true; - } - int timeout = -1; if (process_needs_restart) { timeout = (process_needs_restart - gettime()) * 1000; @@ -1105,24 +1107,12 @@ int main(int argc, char** argv) { bootchart_sample(&timeout); - int nr = TEMP_FAILURE_RETRY(poll(ufds, fd_count, timeout)); - if (nr <= 0) { - if (nr == -1) { - ERROR("poll failed: %s\n", strerror(errno)); - } - continue; - } - - for (size_t i = 0; i < fd_count; i++) { - if (ufds[i].revents & POLLIN) { - if (ufds[i].fd == get_property_set_fd()) { - handle_property_set_fd(); - } else if (ufds[i].fd == get_keychord_fd()) { - handle_keychord(); - } else if (ufds[i].fd == get_signal_fd()) { - handle_signal(); - } - } + epoll_event ev; + int nr = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd, &ev, 1, timeout)); + if (nr == -1) { + ERROR("epoll_wait failed: %s\n", strerror(errno)); + } else if (nr == 1) { + ((void (*)()) ev.data.ptr)(); } } diff --git a/init/init.h b/init/init.h index a104af607..1cabb147e 100644 --- a/init/init.h +++ b/init/init.h @@ -155,4 +155,6 @@ int selinux_reload_policy(void); void zap_stdio(void); +void register_epoll_handler(int fd, void (*fn)()); + #endif /* _INIT_INIT_H */ diff --git a/init/keychords.cpp b/init/keychords.cpp index 27894a2e8..10d9573f2 100644 --- a/init/keychords.cpp +++ b/init/keychords.cpp @@ -62,37 +62,7 @@ void add_service_keycodes(struct service *svc) } } -void keychord_init() -{ - int fd, ret; - - service_for_each(add_service_keycodes); - - /* nothing to do if no services require keychords */ - if (!keychords) - return; - - fd = open("/dev/keychord", O_RDWR | O_CLOEXEC); - if (fd < 0) { - ERROR("could not open /dev/keychord\n"); - return; - } - - ret = write(fd, keychords, keychords_length); - if (ret != keychords_length) { - ERROR("could not configure /dev/keychord %d: %s\n", ret, strerror(errno)); - close(fd); - fd = -1; - } - - free(keychords); - keychords = 0; - - keychord_fd = fd; -} - -void handle_keychord() -{ +static void handle_keychord() { struct service *svc; char adb_enabled[PROP_VALUE_MAX]; int ret; @@ -117,7 +87,28 @@ void handle_keychord() } } -int get_keychord_fd() -{ - return keychord_fd; +void keychord_init() { + service_for_each(add_service_keycodes); + + // Nothing to do if no services require keychords. + if (!keychords) { + return; + } + + keychord_fd = TEMP_FAILURE_RETRY(open("/dev/keychord", O_RDWR | O_CLOEXEC)); + if (keychord_fd == -1) { + ERROR("could not open /dev/keychord: %s\n", strerror(errno)); + return; + } + + int ret = write(keychord_fd, keychords, keychords_length); + if (ret != keychords_length) { + ERROR("could not configure /dev/keychord %d: %s\n", ret, strerror(errno)); + close(keychord_fd); + } + + free(keychords); + keychords = nullptr; + + register_epoll_handler(keychord_fd, handle_keychord); } diff --git a/init/keychords.h b/init/keychords.h index 070b85891..d2723b71c 100644 --- a/init/keychords.h +++ b/init/keychords.h @@ -19,9 +19,7 @@ struct service; -void add_service_keycodes(struct service *svc); -void keychord_init(void); -void handle_keychord(void); -int get_keychord_fd(void); +void add_service_keycodes(service*); +void keychord_init(); #endif diff --git a/init/property_service.cpp b/init/property_service.cpp index 94c5fd902..930ef8213 100644 --- a/init/property_service.cpp +++ b/init/property_service.cpp @@ -246,7 +246,7 @@ int property_set(const char* name, const char* value) { return rc; } -void handle_property_set_fd() +static void handle_property_set_fd() { prop_msg msg; int s; @@ -527,8 +527,6 @@ void start_property_service() { } listen(property_set_fd, 8); -} -int get_property_set_fd() { - return property_set_fd; + register_epoll_handler(property_set_fd, handle_property_set_fd); } diff --git a/init/property_service.h b/init/property_service.h index 825a7dd2a..a27053d93 100644 --- a/init/property_service.h +++ b/init/property_service.h @@ -20,7 +20,6 @@ #include #include -extern void handle_property_set_fd(void); extern void property_init(void); extern void property_load_boot_defaults(void); extern void load_persist_props(void); @@ -30,7 +29,6 @@ void get_property_workspace(int *fd, int *sz); extern int __property_get(const char *name, char *value); extern int property_set(const char *name, const char *value); extern bool properties_initialized(); -int get_property_set_fd(void); #ifndef __clang__ extern void __property_get_size_error() diff --git a/init/signal_handler.cpp b/init/signal_handler.cpp index 37d21bc65..39a466dee 100644 --- a/init/signal_handler.cpp +++ b/init/signal_handler.cpp @@ -147,7 +147,7 @@ static void reap_any_outstanding_children() { } } -void handle_signal() { +static void handle_signal() { // Clear outstanding requests. char buf[32]; read(signal_read_fd, buf, sizeof(buf)); @@ -161,7 +161,7 @@ static void SIGCHLD_handler(int) { } } -void signal_init() { +void signal_handler_init() { // Create a signalling mechanism for SIGCHLD. int s[2]; if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0, s) == -1) { @@ -180,8 +180,6 @@ void signal_init() { sigaction(SIGCHLD, &act, 0); reap_any_outstanding_children(); -} -int get_signal_fd() { - return signal_read_fd; + register_epoll_handler(signal_read_fd, handle_signal); } diff --git a/init/signal_handler.h b/init/signal_handler.h index b092ccb6e..449b4af80 100644 --- a/init/signal_handler.h +++ b/init/signal_handler.h @@ -17,8 +17,6 @@ #ifndef _INIT_SIGNAL_HANDLER_H_ #define _INIT_SIGNAL_HANDLER_H_ -void signal_init(void); -void handle_signal(void); -int get_signal_fd(void); +void signal_handler_init(void); #endif