summaryrefslogtreecommitdiffstats
path: root/init/init.c
diff options
context:
space:
mode:
Diffstat (limited to 'init/init.c')
-rwxr-xr-xinit/init.c723
1 files changed, 237 insertions, 486 deletions
diff --git a/init/init.c b/init/init.c
index 4d98cc2..8f95da7 100755
--- a/init/init.c
+++ b/init/init.c
@@ -25,27 +25,32 @@
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/poll.h>
-#include <time.h>
#include <errno.h>
#include <stdarg.h>
#include <mtd/mtd-user.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
-#include <sys/reboot.h>
+#include <libgen.h>
#include <cutils/sockets.h>
#include <cutils/iosched_policy.h>
+#include <private/android_filesystem_config.h>
#include <termios.h>
-#include <linux/kd.h>
-#include <linux/keychord.h>
#include <sys/system_properties.h>
#include "devices.h"
#include "init.h"
+#include "list.h"
+#include "log.h"
#include "property_service.h"
#include "bootchart.h"
+#include "signal_handler.h"
+#include "keychords.h"
+#include "init_parser.h"
+#include "util.h"
+#include "ueventd.h"
static int property_triggers_enabled = 0;
@@ -62,11 +67,12 @@ static char bootloader[32];
static char hardware[32];
static unsigned revision = 0;
static char qemu[32];
-static struct input_keychord *keychords = 0;
-static int keychords_count = 0;
-static int keychords_length = 0;
-static void notify_service_state(const char *name, const char *state)
+static struct action *cur_action = NULL;
+static struct command *cur_command = NULL;
+static struct listnode *command_queue = NULL;
+
+void notify_service_state(const char *name, const char *state)
{
char pname[PROP_NAME_MAX];
int len = strlen(name);
@@ -122,24 +128,6 @@ static void open_console()
close(fd);
}
-/*
- * gettime() - returns the time in seconds of the system's monotonic clock or
- * zero on error.
- */
-static time_t gettime(void)
-{
- struct timespec ts;
- int ret;
-
- ret = clock_gettime(CLOCK_MONOTONIC, &ts);
- if (ret < 0) {
- ERROR("clock_gettime(CLOCK_MONOTONIC) failed: %s\n", strerror(errno));
- return 0;
- }
-
- return ts.tv_sec;
-}
-
static void publish_socket(const char *name, int fd)
{
char key[64] = ANDROID_SOCKET_ENV_PREFIX;
@@ -208,9 +196,11 @@ void service_start(struct service *svc, const char *dynamic_args)
char tmp[32];
int fd, sz;
- get_property_workspace(&fd, &sz);
- sprintf(tmp, "%d,%d", dup(fd), sz);
- add_environment("ANDROID_PROPERTY_WORKSPACE", tmp);
+ if (properties_inited()) {
+ get_property_workspace(&fd, &sz);
+ sprintf(tmp, "%d,%d", dup(fd), sz);
+ add_environment("ANDROID_PROPERTY_WORKSPACE", tmp);
+ }
for (ei = svc->envvars; ei; ei = ei->next)
add_environment(ei->name, ei->value);
@@ -266,7 +256,7 @@ void service_start(struct service *svc, const char *dynamic_args)
ERROR("cannot execve('%s'): %s\n", svc->args[0], strerror(errno));
}
} else {
- char *arg_ptrs[SVC_MAXARGS+1];
+ char *arg_ptrs[INIT_PARSER_MAXARGS+1];
int arg_idx = svc->nargs;
char *tmp = strdup(dynamic_args);
char *next = tmp;
@@ -277,7 +267,7 @@ void service_start(struct service *svc, const char *dynamic_args)
while((bword = strsep(&next, " "))) {
arg_ptrs[arg_idx++] = bword;
- if (arg_idx == SVC_MAXARGS)
+ if (arg_idx == INIT_PARSER_MAXARGS)
break;
}
arg_ptrs[arg_idx] = '\0';
@@ -296,7 +286,8 @@ void service_start(struct service *svc, const char *dynamic_args)
svc->pid = pid;
svc->flags |= SVC_RUNNING;
- notify_service_state(svc->name, "running");
+ if (properties_inited())
+ notify_service_state(svc->name, "running");
}
void service_stop(struct service *svc)
@@ -322,90 +313,8 @@ void service_stop(struct service *svc)
void property_changed(const char *name, const char *value)
{
- if (property_triggers_enabled) {
+ if (property_triggers_enabled)
queue_property_triggers(name, value);
- drain_action_queue();
- }
-}
-
-#define CRITICAL_CRASH_THRESHOLD 4 /* if we crash >4 times ... */
-#define CRITICAL_CRASH_WINDOW (4*60) /* ... in 4 minutes, goto recovery*/
-
-static int wait_for_one_process(int block)
-{
- pid_t pid;
- int status;
- struct service *svc;
- struct socketinfo *si;
- time_t now;
- struct listnode *node;
- struct command *cmd;
-
- while ( (pid = waitpid(-1, &status, block ? 0 : WNOHANG)) == -1 && errno == EINTR );
- if (pid <= 0) return -1;
- INFO("waitpid returned pid %d, status = %08x\n", pid, status);
-
- svc = service_find_by_pid(pid);
- if (!svc) {
- ERROR("untracked pid %d exited\n", pid);
- return 0;
- }
-
- NOTICE("process '%s', pid %d exited\n", svc->name, pid);
-
- if (!(svc->flags & SVC_ONESHOT)) {
- kill(-pid, SIGKILL);
- NOTICE("process '%s' killing any children in process group\n", svc->name);
- }
-
- /* remove any sockets we may have created */
- for (si = svc->sockets; si; si = si->next) {
- char tmp[128];
- snprintf(tmp, sizeof(tmp), ANDROID_SOCKET_DIR"/%s", si->name);
- unlink(tmp);
- }
-
- svc->pid = 0;
- svc->flags &= (~SVC_RUNNING);
-
- /* oneshot processes go into the disabled state on exit */
- if (svc->flags & SVC_ONESHOT) {
- svc->flags |= SVC_DISABLED;
- }
-
- /* disabled processes do not get restarted automatically */
- if (svc->flags & SVC_DISABLED) {
- notify_service_state(svc->name, "stopped");
- return 0;
- }
-
- now = gettime();
- if (svc->flags & SVC_CRITICAL) {
- if (svc->time_crashed + CRITICAL_CRASH_WINDOW >= now) {
- if (++svc->nr_crashed > CRITICAL_CRASH_THRESHOLD) {
- ERROR("critical process '%s' exited %d times in %d minutes; "
- "rebooting into recovery mode\n", svc->name,
- CRITICAL_CRASH_THRESHOLD, CRITICAL_CRASH_WINDOW / 60);
- sync();
- __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
- LINUX_REBOOT_CMD_RESTART2, "recovery");
- return 0;
- }
- } else {
- svc->time_crashed = now;
- svc->nr_crashed = 1;
- }
- }
-
- svc->flags |= SVC_RESTARTING;
-
- /* Execute all onrestart commands for this service. */
- list_for_each(node, &svc->onrestart.commands) {
- cmd = node_to_item(node, struct command, clist);
- cmd->func(cmd->nargs, cmd->args);
- }
- notify_service_state(svc->name, "restarting");
- return 0;
}
static void restart_service_if_needed(struct service *svc)
@@ -431,13 +340,6 @@ static void restart_processes()
restart_service_if_needed);
}
-static int signal_fd = -1;
-
-static void sigchld_handler(int s)
-{
- write(signal_fd, &s, 1);
-}
-
static void msg_start(const char *name)
{
struct service *svc;
@@ -486,78 +388,6 @@ void handle_control_message(const char *msg, const char *arg)
}
}
-#define MAX_MTD_PARTITIONS 16
-
-static struct {
- char name[16];
- int number;
-} mtd_part_map[MAX_MTD_PARTITIONS];
-
-static int mtd_part_count = -1;
-
-static void find_mtd_partitions(void)
-{
- int fd;
- char buf[1024];
- char *pmtdbufp;
- ssize_t pmtdsize;
- int r;
-
- fd = open("/proc/mtd", O_RDONLY);
- if (fd < 0)
- return;
-
- buf[sizeof(buf) - 1] = '\0';
- pmtdsize = read(fd, buf, sizeof(buf) - 1);
- pmtdbufp = buf;
- while (pmtdsize > 0) {
- int mtdnum, mtdsize, mtderasesize;
- char mtdname[16];
- mtdname[0] = '\0';
- mtdnum = -1;
- r = sscanf(pmtdbufp, "mtd%d: %x %x %15s",
- &mtdnum, &mtdsize, &mtderasesize, mtdname);
- if ((r == 4) && (mtdname[0] == '"')) {
- char *x = strchr(mtdname + 1, '"');
- if (x) {
- *x = 0;
- }
- INFO("mtd partition %d, %s\n", mtdnum, mtdname + 1);
- if (mtd_part_count < MAX_MTD_PARTITIONS) {
- strcpy(mtd_part_map[mtd_part_count].name, mtdname + 1);
- mtd_part_map[mtd_part_count].number = mtdnum;
- mtd_part_count++;
- } else {
- ERROR("too many mtd partitions\n");
- }
- }
- while (pmtdsize > 0 && *pmtdbufp != '\n') {
- pmtdbufp++;
- pmtdsize--;
- }
- if (pmtdsize > 0) {
- pmtdbufp++;
- pmtdsize--;
- }
- }
- close(fd);
-}
-
-int mtd_name_to_number(const char *name)
-{
- int n;
- if (mtd_part_count < 0) {
- mtd_part_count = 0;
- find_mtd_partitions();
- }
- for (n = 0; n < mtd_part_count; n++) {
- if (!strcmp(name, mtd_part_map[n].name)) {
- return mtd_part_map[n].number;
- }
- }
- return -1;
-}
-
static void import_kernel_nv(char *name, int in_qemu)
{
char *value = strchr(name, '=');
@@ -585,8 +415,6 @@ static void import_kernel_nv(char *name, int in_qemu)
strlcpy(bootloader, value, sizeof(bootloader));
} else if (!strcmp(name,"androidboot.hardware")) {
strlcpy(hardware, value, sizeof(hardware));
- } else {
- qemu_cmdline(name, value);
}
} else {
/* in the emulator, export any kernel option with the
@@ -631,198 +459,208 @@ static void import_kernel_cmdline(int in_qemu)
chmod("/proc/cmdline", 0440);
}
-static void get_hardware_name(void)
+static struct command *get_first_command(struct action *act)
{
- char data[1024];
- int fd, n;
- char *x, *hw, *rev;
+ struct listnode *node;
+ node = list_head(&act->commands);
+ if (!node)
+ return NULL;
- /* Hardware string was provided on kernel command line */
- if (hardware[0])
- return;
+ return node_to_item(node, struct command, clist);
+}
- fd = open("/proc/cpuinfo", O_RDONLY);
- if (fd < 0) return;
+static struct command *get_next_command(struct action *act, struct command *cmd)
+{
+ struct listnode *node;
+ node = cmd->clist.next;
+ if (!node)
+ return NULL;
+ if (node == &act->commands)
+ return NULL;
- n = read(fd, data, 1023);
- close(fd);
- if (n < 0) return;
-
- data[n] = 0;
- hw = strstr(data, "\nHardware");
- rev = strstr(data, "\nRevision");
-
- if (hw) {
- x = strstr(hw, ": ");
- if (x) {
- x += 2;
- n = 0;
- while (*x && !isspace(*x)) {
- hardware[n++] = tolower(*x);
- x++;
- if (n == 31) break;
- }
- hardware[n] = 0;
- }
- }
+ return node_to_item(node, struct command, clist);
+}
- if (rev) {
- x = strstr(rev, ": ");
- if (x) {
- revision = strtoul(x + 2, 0, 16);
- }
- }
+static int is_last_command(struct action *act, struct command *cmd)
+{
+ return (list_tail(&act->commands) == &cmd->clist);
}
-void drain_action_queue(void)
+void execute_one_command(void)
{
- struct listnode *node;
- struct command *cmd;
- struct action *act;
int ret;
- while ((act = action_remove_queue_head())) {
- INFO("processing action %p (%s)\n", act, act->name);
- list_for_each(node, &act->commands) {
- cmd = node_to_item(node, struct command, clist);
- ret = cmd->func(cmd->nargs, cmd->args);
- INFO("command '%s' r=%d\n", cmd->args[0], ret);
- }
+ if (!cur_action || !cur_command || is_last_command(cur_action, cur_command)) {
+ cur_action = action_remove_queue_head();
+ cur_command = NULL;
+ if (!cur_action)
+ return;
+ INFO("processing action %p (%s)\n", cur_action, cur_action->name);
+ cur_command = get_first_command(cur_action);
+ } else {
+ cur_command = get_next_command(cur_action, cur_command);
}
+
+ if (!cur_command)
+ return;
+
+ ret = cur_command->func(cur_command->nargs, cur_command->args);
+ INFO("command '%s' r=%d\n", cur_command->args[0], ret);
}
-void open_devnull_stdio(void)
+static int wait_for_coldboot_done_action(int nargs, char **args)
{
- int fd;
- static const char *name = "/dev/__null__";
- if (mknod(name, S_IFCHR | 0600, (1 << 8) | 3) == 0) {
- fd = open(name, O_RDWR);
- unlink(name);
- if (fd >= 0) {
- dup2(fd, 0);
- dup2(fd, 1);
- dup2(fd, 2);
- if (fd > 2) {
- close(fd);
- }
- return;
- }
- }
+ int ret;
+ INFO("wait for %s\n", coldboot_done);
+ ret = wait_for_file(coldboot_done, COMMAND_RETRY_TIMEOUT);
+ if (ret)
+ ERROR("Timed out waiting for %s\n", coldboot_done);
+ return ret;
+}
- exit(1);
+static int property_init_action(int nargs, char **args)
+{
+ INFO("property init\n");
+ property_init();
+ return 0;
}
-void add_service_keycodes(struct service *svc)
+static int keychord_init_action(int nargs, char **args)
{
- struct input_keychord *keychord;
- int i, size;
-
- if (svc->keycodes) {
- /* add a new keychord to the list */
- size = sizeof(*keychord) + svc->nkeycodes * sizeof(keychord->keycodes[0]);
- keychords = realloc(keychords, keychords_length + size);
- if (!keychords) {
- ERROR("could not allocate keychords\n");
- keychords_length = 0;
- keychords_count = 0;
- return;
- }
+ keychord_init();
+ return 0;
+}
- keychord = (struct input_keychord *)((char *)keychords + keychords_length);
- keychord->version = KEYCHORD_VERSION;
- keychord->id = keychords_count + 1;
- keychord->count = svc->nkeycodes;
- svc->keychord_id = keychord->id;
+static int console_init_action(int nargs, char **args)
+{
+ int fd;
+ char tmp[PROP_VALUE_MAX];
+
+ if (console[0]) {
+ snprintf(tmp, sizeof(tmp), "/dev/%s", console);
+ console_name = strdup(tmp);
+ }
- for (i = 0; i < svc->nkeycodes; i++) {
- keychord->keycodes[i] = svc->keycodes[i];
+ fd = open(console_name, O_RDWR);
+ if (fd >= 0)
+ have_console = 1;
+ close(fd);
+
+ if( load_565rle_image(INIT_IMAGE_FILE) ) {
+ fd = open("/dev/tty0", O_WRONLY);
+ if (fd >= 0) {
+ const char *msg;
+ msg = "\n"
+ "\n"
+ "\n"
+ "\n"
+ "\n"
+ "\n"
+ "\n" // console is 40 cols x 30 lines
+ "\n"
+ "\n"
+ "\n"
+ "\n"
+ "\n"
+ "\n"
+ "\n"
+ " A N D R O I D ";
+ write(fd, msg, strlen(msg));
+ close(fd);
}
- keychords_count++;
- keychords_length += size;
}
+ return 0;
}
-int open_keychord()
+static int set_init_properties_action(int nargs, char **args)
{
- int fd, ret;
+ char tmp[PROP_VALUE_MAX];
- service_for_each(add_service_keycodes);
-
- /* nothing to do if no services require keychords */
- if (!keychords)
- return -1;
-
- fd = open("/dev/keychord", O_RDWR);
- if (fd < 0) {
- ERROR("could not open /dev/keychord\n");
- return fd;
- }
- fcntl(fd, F_SETFD, FD_CLOEXEC);
+ if (qemu[0])
+ import_kernel_cmdline(1);
- ret = write(fd, keychords, keychords_length);
- if (ret != keychords_length) {
- ERROR("could not configure /dev/keychord %d (%d)\n", ret, errno);
- close(fd);
- fd = -1;
- }
+ if (!strcmp(bootmode,"factory"))
+ property_set("ro.factorytest", "1");
+ else if (!strcmp(bootmode,"factory2"))
+ property_set("ro.factorytest", "2");
+ else
+ property_set("ro.factorytest", "0");
- free(keychords);
- keychords = 0;
+ property_set("ro.serialno", serialno[0] ? serialno : "");
+ property_set("ro.bootmode", bootmode[0] ? bootmode : "unknown");
+ property_set("ro.baseband", baseband[0] ? baseband : "unknown");
+ property_set("ro.carrier", carrier[0] ? carrier : "unknown");
+ property_set("ro.bootloader", bootloader[0] ? bootloader : "unknown");
- return fd;
+ property_set("ro.hardware", hardware);
+ snprintf(tmp, PROP_VALUE_MAX, "%d", revision);
+ property_set("ro.revision", tmp);
+ return 0;
}
-void handle_keychord(int fd)
+static int property_service_init_action(int nargs, char **args)
{
- struct service *svc;
- char* debuggable;
- char* adb_enabled;
- int ret;
- __u16 id;
-
- // only handle keychords if ro.debuggable is set or adb is enabled.
- // the logic here is that bugreports should be enabled in userdebug or eng builds
- // and on user builds for users that are developers.
- debuggable = property_get("ro.debuggable");
- adb_enabled = property_get("init.svc.adbd");
- if ((debuggable && !strcmp(debuggable, "1")) ||
- (adb_enabled && !strcmp(adb_enabled, "running"))) {
- ret = read(fd, &id, sizeof(id));
- if (ret != sizeof(id)) {
- ERROR("could not read keychord id\n");
- return;
- }
+ /* read any property files on system or data and
+ * fire up the property service. This must happen
+ * after the ro.foo properties are set above so
+ * that /data/local.prop cannot interfere with them.
+ */
+ start_property_service();
+ return 0;
+}
- svc = service_find_by_keychord(id);
- if (svc) {
- INFO("starting service %s from keychord\n", svc->name);
- service_start(svc, NULL);
- } else {
- ERROR("service for keychord %d not found\n", id);
- }
+static int signal_init_action(int nargs, char **args)
+{
+ signal_init();
+ return 0;
+}
+
+static int check_startup_action(int nargs, char **args)
+{
+ /* make sure we actually have all the pieces we need */
+ if ((get_property_set_fd() < 0) ||
+ (get_signal_fd() < 0)) {
+ ERROR("init startup failure\n");
+ exit(1);
}
+ return 0;
+}
+
+static int queue_property_triggers_action(int nargs, char **args)
+{
+ queue_all_property_triggers();
+ /* enable property triggers */
+ property_triggers_enabled = 1;
+ return 0;
}
+#if BOOTCHART
+static int bootchart_init_action(int nargs, char **args)
+{
+ bootchart_count = bootchart_init();
+ if (bootchart_count < 0) {
+ ERROR("bootcharting init failure\n");
+ } else if (bootchart_count > 0) {
+ NOTICE("bootcharting started (period=%d ms)\n", bootchart_count*BOOTCHART_POLLING_MS);
+ } else {
+ NOTICE("bootcharting ignored\n");
+ }
+}
+#endif
+
int main(int argc, char **argv)
{
- int device_fd = -1;
- int property_set_fd = -1;
- int signal_recv_fd = -1;
- int keychord_fd = -1;
- int fd_count;
- int s[2];
- int fd;
- struct sigaction act;
- char tmp[PROP_VALUE_MAX];
+ int fd_count = 0;
struct pollfd ufds[4];
char *tmpdev;
char* debuggable;
+ char tmp[32];
+ int property_set_fd_init = 0;
+ int signal_fd_init = 0;
+ int keychord_fd_init = 0;
- act.sa_handler = sigchld_handler;
- act.sa_flags = SA_NOCLDSTOP;
- act.sa_mask = 0;
- act.sa_restorer = NULL;
- sigaction(SIGCHLD, &act, 0);
+ if (!strcmp(basename(argv[0]), "ueventd"))
+ return ueventd_main(argc, argv);
/* clear the umask */
umask(0);
@@ -852,165 +690,82 @@ int main(int argc, char **argv)
log_init();
INFO("reading config file\n");
- parse_config_file("/init.rc");
+ init_parse_config_file("/init.rc");
/* pull the kernel commandline and ramdisk properties file in */
- qemu_init();
import_kernel_cmdline(0);
- get_hardware_name();
+ get_hardware_name(hardware, &revision);
snprintf(tmp, sizeof(tmp), "/init.%s.rc", hardware);
- parse_config_file(tmp);
+ init_parse_config_file(tmp);
action_for_each_trigger("early-init", action_add_queue_tail);
- drain_action_queue();
-
- INFO("device init\n");
- device_fd = device_init();
-
- property_init();
-
- // only listen for keychords if ro.debuggable is true
- keychord_fd = open_keychord();
-
- if (console[0]) {
- snprintf(tmp, sizeof(tmp), "/dev/%s", console);
- console_name = strdup(tmp);
- }
-
- fd = open(console_name, O_RDWR);
- if (fd >= 0)
- have_console = 1;
- close(fd);
-
- if( load_565rle_image(INIT_IMAGE_FILE) ) {
- fd = open("/dev/tty0", O_WRONLY);
- if (fd >= 0) {
- const char *msg;
- msg = "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n" // console is 40 cols x 30 lines
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- " A N D R O I D ";
- write(fd, msg, strlen(msg));
- close(fd);
- }
- }
- if (qemu[0])
- import_kernel_cmdline(1);
-
- if (!strcmp(bootmode,"factory"))
- property_set("ro.factorytest", "1");
- else if (!strcmp(bootmode,"factory2"))
- property_set("ro.factorytest", "2");
- else
- property_set("ro.factorytest", "0");
-
- property_set("ro.serialno", serialno[0] ? serialno : "");
- property_set("ro.bootmode", bootmode[0] ? bootmode : "unknown");
- property_set("ro.baseband", baseband[0] ? baseband : "unknown");
- property_set("ro.carrier", carrier[0] ? carrier : "unknown");
- property_set("ro.bootloader", bootloader[0] ? bootloader : "unknown");
-
- property_set("ro.hardware", hardware);
- snprintf(tmp, PROP_VALUE_MAX, "%d", revision);
- property_set("ro.revision", tmp);
+ queue_builtin_action(wait_for_coldboot_done_action, "wait_for_coldboot_done");
+ queue_builtin_action(property_init_action, "property_init");
+ queue_builtin_action(keychord_init_action, "keychord_init");
+ queue_builtin_action(console_init_action, "console_init");
+ queue_builtin_action(set_init_properties_action, "set_init_properties");
/* execute all the boot actions to get us started */
action_for_each_trigger("init", action_add_queue_tail);
- drain_action_queue();
-
- /* read any property files on system or data and
- * fire up the property service. This must happen
- * after the ro.foo properties are set above so
- * that /data/local.prop cannot interfere with them.
- */
- property_set_fd = start_property_service();
-
- /* create a signalling mechanism for the sigchld handler */
- if (socketpair(AF_UNIX, SOCK_STREAM, 0, s) == 0) {
- signal_fd = s[0];
- signal_recv_fd = s[1];
- fcntl(s[0], F_SETFD, FD_CLOEXEC);
- fcntl(s[0], F_SETFL, O_NONBLOCK);
- fcntl(s[1], F_SETFD, FD_CLOEXEC);
- fcntl(s[1], F_SETFL, O_NONBLOCK);
- }
+ action_for_each_trigger("early-fs", action_add_queue_tail);
+ action_for_each_trigger("fs", action_add_queue_tail);
+ action_for_each_trigger("post-fs", action_add_queue_tail);
- /* make sure we actually have all the pieces we need */
- if ((device_fd < 0) ||
- (property_set_fd < 0) ||
- (signal_recv_fd < 0)) {
- ERROR("init startup failure\n");
- return 1;
- }
+ queue_builtin_action(property_service_init_action, "property_service_init");
+ queue_builtin_action(signal_init_action, "signal_init");
+ queue_builtin_action(check_startup_action, "check_startup");
/* execute all the boot actions to get us started */
action_for_each_trigger("early-boot", action_add_queue_tail);
action_for_each_trigger("boot", action_add_queue_tail);
- drain_action_queue();
/* run all property triggers based on current state of the properties */
- queue_all_property_triggers();
- drain_action_queue();
-
- /* enable property triggers */
- property_triggers_enabled = 1;
-
- ufds[0].fd = device_fd;
- ufds[0].events = POLLIN;
- ufds[1].fd = property_set_fd;
- ufds[1].events = POLLIN;
- ufds[2].fd = signal_recv_fd;
- ufds[2].events = POLLIN;
- fd_count = 3;
-
- if (keychord_fd > 0) {
- ufds[3].fd = keychord_fd;
- ufds[3].events = POLLIN;
- fd_count++;
- } else {
- ufds[3].events = 0;
- ufds[3].revents = 0;
- }
+ queue_builtin_action(queue_property_triggers_action, "queue_propety_triggers");
+
#if BOOTCHART
- bootchart_count = bootchart_init();
- if (bootchart_count < 0) {
- ERROR("bootcharting init failure\n");
- } else if (bootchart_count > 0) {
- NOTICE("bootcharting started (period=%d ms)\n", bootchart_count*BOOTCHART_POLLING_MS);
- } else {
- NOTICE("bootcharting ignored\n");
- }
+ queue_builtin_action(bootchart_init_action, "bootchart_init");
#endif
for(;;) {
int nr, i, timeout = -1;
- for (i = 0; i < fd_count; i++)
- ufds[i].revents = 0;
-
- drain_action_queue();
+ execute_one_command();
restart_processes();
+ if (!property_set_fd_init && get_property_set_fd() > 0) {
+ ufds[fd_count].fd = get_property_set_fd();
+ ufds[fd_count].events = POLLIN;
+ ufds[fd_count].revents = 0;
+ fd_count++;
+ property_set_fd_init = 1;
+ }
+ if (!signal_fd_init && get_signal_fd() > 0) {
+ ufds[fd_count].fd = get_signal_fd();
+ ufds[fd_count].events = POLLIN;
+ ufds[fd_count].revents = 0;
+ fd_count++;
+ signal_fd_init = 1;
+ }
+ 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 = 1;
+ }
+
if (process_needs_restart) {
timeout = (process_needs_restart - gettime()) * 1000;
if (timeout < 0)
timeout = 0;
}
+ if (!action_queue_empty() || cur_action)
+ timeout = 0;
+
#if BOOTCHART
if (bootchart_count > 0) {
if (timeout < 0 || timeout > BOOTCHART_POLLING_MS)
@@ -1021,25 +776,21 @@ int main(int argc, char **argv)
}
}
#endif
+
nr = poll(ufds, fd_count, timeout);
if (nr <= 0)
continue;
- if (ufds[2].revents == POLLIN) {
- /* we got a SIGCHLD - reap and restart as needed */
- read(signal_recv_fd, tmp, sizeof(tmp));
- while (!wait_for_one_process(0))
- ;
- continue;
+ for (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();
+ }
}
-
- if (ufds[0].revents == POLLIN)
- handle_device_fd(device_fd);
-
- if (ufds[1].revents == POLLIN)
- handle_property_set_fd(property_set_fd);
- if (ufds[3].revents == POLLIN)
- handle_keychord(keychord_fd);
}
return 0;