init.c revision 77d0c65b950570edd5241a8f2ebecfc3acbc5135
1/* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <stdio.h> 18#include <stdlib.h> 19#include <string.h> 20#include <unistd.h> 21#include <fcntl.h> 22#include <ctype.h> 23#include <signal.h> 24#include <sys/wait.h> 25#include <sys/mount.h> 26#include <sys/stat.h> 27#include <sys/poll.h> 28#include <time.h> 29#include <errno.h> 30#include <stdarg.h> 31#include <mtd/mtd-user.h> 32#include <sys/types.h> 33#include <sys/socket.h> 34#include <sys/un.h> 35#include <sys/reboot.h> 36 37#include <cutils/sockets.h> 38#include <termios.h> 39#include <linux/kd.h> 40 41#include <sys/system_properties.h> 42 43#include "devices.h" 44#include "init.h" 45#include "property_service.h" 46#include "bootchart.h" 47 48static int property_triggers_enabled = 0; 49 50#if BOOTCHART 51static int bootchart_count; 52#endif 53 54static char console[32]; 55static char serialno[32]; 56static char bootmode[32]; 57static char baseband[32]; 58static char carrier[32]; 59static char bootloader[32]; 60static char hardware[32]; 61static unsigned revision = 0; 62static char qemu[32]; 63 64static void drain_action_queue(void); 65 66static void notify_service_state(const char *name, const char *state) 67{ 68 char pname[PROP_NAME_MAX]; 69 int len = strlen(name); 70 if ((len + 10) > PROP_NAME_MAX) 71 return; 72 snprintf(pname, sizeof(pname), "init.svc.%s", name); 73 property_set(pname, state); 74} 75 76static int have_console; 77static char *console_name = "/dev/console"; 78static time_t process_needs_restart; 79 80static const char *ENV[32]; 81 82/* add_environment - add "key=value" to the current environment */ 83int add_environment(const char *key, const char *val) 84{ 85 int n; 86 87 for (n = 0; n < 31; n++) { 88 if (!ENV[n]) { 89 size_t len = strlen(key) + strlen(val) + 2; 90 char *entry = malloc(len); 91 snprintf(entry, len, "%s=%s", key, val); 92 ENV[n] = entry; 93 return 0; 94 } 95 } 96 97 return 1; 98} 99 100static void zap_stdio(void) 101{ 102 int fd; 103 fd = open("/dev/null", O_RDWR); 104 dup2(fd, 0); 105 dup2(fd, 1); 106 dup2(fd, 2); 107 close(fd); 108} 109 110static void open_console() 111{ 112 int fd; 113 if ((fd = open(console_name, O_RDWR)) < 0) { 114 fd = open("/dev/null", O_RDWR); 115 } 116 dup2(fd, 0); 117 dup2(fd, 1); 118 dup2(fd, 2); 119 close(fd); 120} 121 122/* 123 * gettime() - returns the time in seconds of the system's monotonic clock or 124 * zero on error. 125 */ 126static time_t gettime(void) 127{ 128 struct timespec ts; 129 int ret; 130 131 ret = clock_gettime(CLOCK_MONOTONIC, &ts); 132 if (ret < 0) { 133 ERROR("clock_gettime(CLOCK_MONOTONIC) failed: %s\n", strerror(errno)); 134 return 0; 135 } 136 137 return ts.tv_sec; 138} 139 140static void publish_socket(const char *name, int fd) 141{ 142 char key[64] = ANDROID_SOCKET_ENV_PREFIX; 143 char val[64]; 144 145 strlcpy(key + sizeof(ANDROID_SOCKET_ENV_PREFIX) - 1, 146 name, 147 sizeof(key) - sizeof(ANDROID_SOCKET_ENV_PREFIX)); 148 snprintf(val, sizeof(val), "%d", fd); 149 add_environment(key, val); 150 151 /* make sure we don't close-on-exec */ 152 fcntl(fd, F_SETFD, 0); 153} 154 155void service_start(struct service *svc) 156{ 157 struct stat s; 158 pid_t pid; 159 int needs_console; 160 int n; 161 162 /* starting a service removes it from the disabled 163 * state and immediately takes it out of the restarting 164 * state if it was in there 165 */ 166 svc->flags &= (~(SVC_DISABLED|SVC_RESTARTING)); 167 svc->time_started = 0; 168 169 /* running processes require no additional work -- if 170 * they're in the process of exiting, we've ensured 171 * that they will immediately restart on exit, unless 172 * they are ONESHOT 173 */ 174 if (svc->flags & SVC_RUNNING) { 175 return; 176 } 177 178 needs_console = (svc->flags & SVC_CONSOLE) ? 1 : 0; 179 if (needs_console && (!have_console)) { 180 ERROR("service '%s' requires console\n", svc->name); 181 svc->flags |= SVC_DISABLED; 182 return; 183 } 184 185 if (stat(svc->args[0], &s) != 0) { 186 ERROR("cannot find '%s', disabling '%s'\n", svc->args[0], svc->name); 187 svc->flags |= SVC_DISABLED; 188 return; 189 } 190 191 NOTICE("starting '%s'\n", svc->name); 192 193 pid = fork(); 194 195 if (pid == 0) { 196 struct socketinfo *si; 197 struct svcenvinfo *ei; 198 char tmp[32]; 199 int fd, sz; 200 201 get_property_workspace(&fd, &sz); 202 sprintf(tmp, "%d,%d", dup(fd), sz); 203 add_environment("ANDROID_PROPERTY_WORKSPACE", tmp); 204 205 for (ei = svc->envvars; ei; ei = ei->next) 206 add_environment(ei->name, ei->value); 207 208 for (si = svc->sockets; si; si = si->next) { 209 int s = create_socket(si->name, 210 !strcmp(si->type, "dgram") ? 211 SOCK_DGRAM : SOCK_STREAM, 212 si->perm, si->uid, si->gid); 213 if (s >= 0) { 214 publish_socket(si->name, s); 215 } 216 } 217 218 if (needs_console) { 219 setsid(); 220 open_console(); 221 } else { 222 zap_stdio(); 223 } 224 225#if 0 226 for (n = 0; svc->args[n]; n++) { 227 INFO("args[%d] = '%s'\n", n, svc->args[n]); 228 } 229 for (n = 0; ENV[n]; n++) { 230 INFO("env[%d] = '%s'\n", n, ENV[n]); 231 } 232#endif 233 234 setpgid(0, getpid()); 235 236 /* as requested, set our gid, supplemental gids, and uid */ 237 if (svc->gid) { 238 setgid(svc->gid); 239 } 240 if (svc->nr_supp_gids) { 241 setgroups(svc->nr_supp_gids, svc->supp_gids); 242 } 243 if (svc->uid) { 244 setuid(svc->uid); 245 } 246 247 if (execve(svc->args[0], (char**) svc->args, (char**) ENV) < 0) { 248 ERROR("cannot execve('%s'): %s\n", svc->args[0], strerror(errno)); 249 } 250 _exit(127); 251 } 252 253 if (pid < 0) { 254 ERROR("failed to start '%s'\n", svc->name); 255 svc->pid = 0; 256 return; 257 } 258 259 svc->time_started = gettime(); 260 svc->pid = pid; 261 svc->flags |= SVC_RUNNING; 262 263 notify_service_state(svc->name, "running"); 264} 265 266void service_stop(struct service *svc) 267{ 268 /* we are no longer running, nor should we 269 * attempt to restart 270 */ 271 svc->flags &= (~(SVC_RUNNING|SVC_RESTARTING)); 272 273 /* if the service has not yet started, prevent 274 * it from auto-starting with its class 275 */ 276 svc->flags |= SVC_DISABLED; 277 278 if (svc->pid) { 279 NOTICE("service '%s' is being killed\n", svc->name); 280 kill(-svc->pid, SIGTERM); 281 notify_service_state(svc->name, "stopping"); 282 } else { 283 notify_service_state(svc->name, "stopped"); 284 } 285} 286 287void property_changed(const char *name, const char *value) 288{ 289 if (property_triggers_enabled) { 290 queue_property_triggers(name, value); 291 drain_action_queue(); 292 } 293} 294 295#define CRITICAL_CRASH_THRESHOLD 4 /* if we crash >4 times ... */ 296#define CRITICAL_CRASH_WINDOW (4*60) /* ... in 4 minutes, goto recovery*/ 297 298static int wait_for_one_process(int block) 299{ 300 pid_t pid; 301 int status; 302 struct service *svc; 303 struct socketinfo *si; 304 time_t now; 305 struct listnode *node; 306 struct command *cmd; 307 308 while ( (pid = waitpid(-1, &status, block ? 0 : WNOHANG)) == -1 && errno == EINTR ); 309 if (pid <= 0) return -1; 310 INFO("waitpid returned pid %d, status = %08x\n", pid, status); 311 312 svc = service_find_by_pid(pid); 313 if (!svc) { 314 ERROR("untracked pid %d exited\n", pid); 315 return 0; 316 } 317 318 NOTICE("process '%s', pid %d exited\n", svc->name, pid); 319 320 if (!(svc->flags & SVC_ONESHOT)) { 321 kill(-pid, SIGKILL); 322 NOTICE("process '%s' killing any children in process group\n", svc->name); 323 } 324 325 /* remove any sockets we may have created */ 326 for (si = svc->sockets; si; si = si->next) { 327 char tmp[128]; 328 snprintf(tmp, sizeof(tmp), ANDROID_SOCKET_DIR"/%s", si->name); 329 unlink(tmp); 330 } 331 332 svc->pid = 0; 333 svc->flags &= (~SVC_RUNNING); 334 335 /* oneshot processes go into the disabled state on exit */ 336 if (svc->flags & SVC_ONESHOT) { 337 svc->flags |= SVC_DISABLED; 338 } 339 340 /* disabled processes do not get restarted automatically */ 341 if (svc->flags & SVC_DISABLED) { 342 notify_service_state(svc->name, "stopped"); 343 return 0; 344 } 345 346 now = gettime(); 347 if (svc->flags & SVC_CRITICAL) { 348 if (svc->time_crashed + CRITICAL_CRASH_WINDOW >= now) { 349 if (++svc->nr_crashed > CRITICAL_CRASH_THRESHOLD) { 350 ERROR("critical process '%s' exited %d times in %d minutes; " 351 "rebooting into recovery mode\n", svc->name, 352 CRITICAL_CRASH_THRESHOLD, CRITICAL_CRASH_WINDOW / 60); 353 sync(); 354 __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, 355 LINUX_REBOOT_CMD_RESTART2, "recovery"); 356 return 0; 357 } 358 } else { 359 svc->time_crashed = now; 360 svc->nr_crashed = 1; 361 } 362 } 363 364 /* Execute all onrestart commands for this service. */ 365 list_for_each(node, &svc->onrestart.commands) { 366 cmd = node_to_item(node, struct command, clist); 367 cmd->func(cmd->nargs, cmd->args); 368 } 369 svc->flags |= SVC_RESTARTING; 370 notify_service_state(svc->name, "restarting"); 371 return 0; 372} 373 374static void restart_service_if_needed(struct service *svc) 375{ 376 time_t next_start_time = svc->time_started + 5; 377 378 if (next_start_time <= gettime()) { 379 svc->flags &= (~SVC_RESTARTING); 380 service_start(svc); 381 return; 382 } 383 384 if ((next_start_time < process_needs_restart) || 385 (process_needs_restart == 0)) { 386 process_needs_restart = next_start_time; 387 } 388} 389 390static void restart_processes() 391{ 392 process_needs_restart = 0; 393 service_for_each_flags(SVC_RESTARTING, 394 restart_service_if_needed); 395} 396 397static int signal_fd = -1; 398 399static void sigchld_handler(int s) 400{ 401 write(signal_fd, &s, 1); 402} 403 404static void msg_start(const char *name) 405{ 406 struct service *svc = service_find_by_name(name); 407 408 if (svc) { 409 service_start(svc); 410 } else { 411 ERROR("no such service '%s'\n", name); 412 } 413} 414 415static void msg_stop(const char *name) 416{ 417 struct service *svc = service_find_by_name(name); 418 419 if (svc) { 420 service_stop(svc); 421 } else { 422 ERROR("no such service '%s'\n"); 423 } 424} 425 426void handle_control_message(const char *msg, const char *arg) 427{ 428 if (!strcmp(msg,"start")) { 429 msg_start(arg); 430 } else if (!strcmp(msg,"stop")) { 431 msg_stop(arg); 432 } else { 433 ERROR("unknown control msg '%s'\n", msg); 434 } 435} 436 437#define MAX_MTD_PARTITIONS 16 438 439static struct { 440 char name[16]; 441 int number; 442} mtd_part_map[MAX_MTD_PARTITIONS]; 443 444static int mtd_part_count = -1; 445 446static void find_mtd_partitions(void) 447{ 448 int fd; 449 char buf[1024]; 450 char *pmtdbufp; 451 ssize_t pmtdsize; 452 int r; 453 454 fd = open("/proc/mtd", O_RDONLY); 455 if (fd < 0) 456 return; 457 458 buf[sizeof(buf) - 1] = '\0'; 459 pmtdsize = read(fd, buf, sizeof(buf) - 1); 460 pmtdbufp = buf; 461 while (pmtdsize > 0) { 462 int mtdnum, mtdsize, mtderasesize; 463 char mtdname[16]; 464 mtdname[0] = '\0'; 465 mtdnum = -1; 466 r = sscanf(pmtdbufp, "mtd%d: %x %x %15s", 467 &mtdnum, &mtdsize, &mtderasesize, mtdname); 468 if ((r == 4) && (mtdname[0] == '"')) { 469 char *x = strchr(mtdname + 1, '"'); 470 if (x) { 471 *x = 0; 472 } 473 INFO("mtd partition %d, %s\n", mtdnum, mtdname + 1); 474 if (mtd_part_count < MAX_MTD_PARTITIONS) { 475 strcpy(mtd_part_map[mtd_part_count].name, mtdname + 1); 476 mtd_part_map[mtd_part_count].number = mtdnum; 477 mtd_part_count++; 478 } else { 479 ERROR("too many mtd partitions\n"); 480 } 481 } 482 while (pmtdsize > 0 && *pmtdbufp != '\n') { 483 pmtdbufp++; 484 pmtdsize--; 485 } 486 if (pmtdsize > 0) { 487 pmtdbufp++; 488 pmtdsize--; 489 } 490 } 491 close(fd); 492} 493 494int mtd_name_to_number(const char *name) 495{ 496 int n; 497 if (mtd_part_count < 0) { 498 mtd_part_count = 0; 499 find_mtd_partitions(); 500 } 501 for (n = 0; n < mtd_part_count; n++) { 502 if (!strcmp(name, mtd_part_map[n].name)) { 503 return mtd_part_map[n].number; 504 } 505 } 506 return -1; 507} 508 509static void import_kernel_nv(char *name, int in_qemu) 510{ 511 char *value = strchr(name, '='); 512 513 if (value == 0) return; 514 *value++ = 0; 515 if (*name == 0) return; 516 517 if (!in_qemu) 518 { 519 /* on a real device, white-list the kernel options */ 520 if (!strcmp(name,"qemu")) { 521 strlcpy(qemu, value, sizeof(qemu)); 522 } else if (!strcmp(name,"androidboot.console")) { 523 strlcpy(console, value, sizeof(console)); 524 } else if (!strcmp(name,"androidboot.mode")) { 525 strlcpy(bootmode, value, sizeof(bootmode)); 526 } else if (!strcmp(name,"androidboot.serialno")) { 527 strlcpy(serialno, value, sizeof(serialno)); 528 } else if (!strcmp(name,"androidboot.baseband")) { 529 strlcpy(baseband, value, sizeof(baseband)); 530 } else if (!strcmp(name,"androidboot.carrier")) { 531 strlcpy(carrier, value, sizeof(carrier)); 532 } else if (!strcmp(name,"androidboot.bootloader")) { 533 strlcpy(bootloader, value, sizeof(bootloader)); 534 } else if (!strcmp(name,"androidboot.hardware")) { 535 strlcpy(hardware, value, sizeof(hardware)); 536 } else { 537 qemu_cmdline(name, value); 538 } 539 } else { 540 /* in the emulator, export any kernel option with the 541 * ro.kernel. prefix */ 542 char buff[32]; 543 int len = snprintf( buff, sizeof(buff), "ro.kernel.%s", name ); 544 if (len < (int)sizeof(buff)) { 545 property_set( buff, value ); 546 } 547 } 548} 549 550static void import_kernel_cmdline(int in_qemu) 551{ 552 char cmdline[1024]; 553 char *ptr; 554 int fd; 555 556 fd = open("/proc/cmdline", O_RDONLY); 557 if (fd >= 0) { 558 int n = read(fd, cmdline, 1023); 559 if (n < 0) n = 0; 560 561 /* get rid of trailing newline, it happens */ 562 if (n > 0 && cmdline[n-1] == '\n') n--; 563 564 cmdline[n] = 0; 565 close(fd); 566 } else { 567 cmdline[0] = 0; 568 } 569 570 ptr = cmdline; 571 while (ptr && *ptr) { 572 char *x = strchr(ptr, ' '); 573 if (x != 0) *x++ = 0; 574 import_kernel_nv(ptr, in_qemu); 575 ptr = x; 576 } 577 578 /* don't expose the raw commandline to nonpriv processes */ 579 chmod("/proc/cmdline", 0440); 580} 581 582static void get_hardware_name(void) 583{ 584 char data[1024]; 585 int fd, n; 586 char *x, *hw, *rev; 587 588 /* Hardware string was provided on kernel command line */ 589 if (hardware[0]) 590 return; 591 592 fd = open("/proc/cpuinfo", O_RDONLY); 593 if (fd < 0) return; 594 595 n = read(fd, data, 1023); 596 close(fd); 597 if (n < 0) return; 598 599 data[n] = 0; 600 hw = strstr(data, "\nHardware"); 601 rev = strstr(data, "\nRevision"); 602 603 if (hw) { 604 x = strstr(hw, ": "); 605 if (x) { 606 x += 2; 607 n = 0; 608 while (*x && !isspace(*x)) { 609 hardware[n++] = tolower(*x); 610 x++; 611 if (n == 31) break; 612 } 613 hardware[n] = 0; 614 } 615 } 616 617 if (rev) { 618 x = strstr(rev, ": "); 619 if (x) { 620 revision = strtoul(x + 2, 0, 16); 621 } 622 } 623} 624 625static void drain_action_queue(void) 626{ 627 struct listnode *node; 628 struct command *cmd; 629 struct action *act; 630 int ret; 631 632 while ((act = action_remove_queue_head())) { 633 INFO("processing action %p (%s)\n", act, act->name); 634 list_for_each(node, &act->commands) { 635 cmd = node_to_item(node, struct command, clist); 636 ret = cmd->func(cmd->nargs, cmd->args); 637 INFO("command '%s' r=%d\n", cmd->args[0], ret); 638 } 639 } 640} 641 642void open_devnull_stdio(void) 643{ 644 int fd; 645 static const char *name = "/dev/__null__"; 646 if (mknod(name, S_IFCHR | 0600, (1 << 8) | 3) == 0) { 647 fd = open(name, O_RDWR); 648 unlink(name); 649 if (fd >= 0) { 650 dup2(fd, 0); 651 dup2(fd, 1); 652 dup2(fd, 2); 653 if (fd > 2) { 654 close(fd); 655 } 656 return; 657 } 658 } 659 660 exit(1); 661} 662 663int main(int argc, char **argv) 664{ 665 int device_fd = -1; 666 int property_set_fd = -1; 667 int signal_recv_fd = -1; 668 int s[2]; 669 int fd; 670 struct sigaction act; 671 char tmp[PROP_VALUE_MAX]; 672 struct pollfd ufds[4]; 673 char *tmpdev; 674 675 act.sa_handler = sigchld_handler; 676 act.sa_flags = SA_NOCLDSTOP; 677 act.sa_mask = 0; 678 act.sa_restorer = NULL; 679 sigaction(SIGCHLD, &act, 0); 680 681 /* clear the umask */ 682 umask(0); 683 684 /* Get the basic filesystem setup we need put 685 * together in the initramdisk on / and then we'll 686 * let the rc file figure out the rest. 687 */ 688 mkdir("/dev", 0755); 689 mkdir("/proc", 0755); 690 mkdir("/sys", 0755); 691 692 mount("tmpfs", "/dev", "tmpfs", 0, "mode=0755"); 693 mkdir("/dev/pts", 0755); 694 mkdir("/dev/socket", 0755); 695 mount("devpts", "/dev/pts", "devpts", 0, NULL); 696 mount("proc", "/proc", "proc", 0, NULL); 697 mount("sysfs", "/sys", "sysfs", 0, NULL); 698 699 /* We must have some place other than / to create the 700 * device nodes for kmsg and null, otherwise we won't 701 * be able to remount / read-only later on. 702 * Now that tmpfs is mounted on /dev, we can actually 703 * talk to the outside world. 704 */ 705 open_devnull_stdio(); 706 log_init(); 707 708 INFO("reading config file\n"); 709 parse_config_file("/init.rc"); 710 711 /* pull the kernel commandline and ramdisk properties file in */ 712 qemu_init(); 713 import_kernel_cmdline(0); 714 715 get_hardware_name(); 716 snprintf(tmp, sizeof(tmp), "/init.%s.rc", hardware); 717 parse_config_file(tmp); 718 719 action_for_each_trigger("early-init", action_add_queue_tail); 720 drain_action_queue(); 721 722 INFO("device init\n"); 723 device_fd = device_init(); 724 725 property_init(); 726 727 if (console[0]) { 728 snprintf(tmp, sizeof(tmp), "/dev/%s", console); 729 console_name = strdup(tmp); 730 } 731 732 fd = open(console_name, O_RDWR); 733 if (fd >= 0) 734 have_console = 1; 735 close(fd); 736 737 if( load_565rle_image(INIT_IMAGE_FILE) ) { 738 fd = open("/dev/tty0", O_WRONLY); 739 if (fd >= 0) { 740 const char *msg; 741 msg = "\n" 742 "\n" 743 "\n" 744 "\n" 745 "\n" 746 "\n" 747 "\n" // console is 40 cols x 30 lines 748 "\n" 749 "\n" 750 "\n" 751 "\n" 752 "\n" 753 "\n" 754 "\n" 755 " A N D R O I D "; 756 write(fd, msg, strlen(msg)); 757 close(fd); 758 } 759 } 760 761 if (qemu[0]) 762 import_kernel_cmdline(1); 763 764 if (!strcmp(bootmode,"factory")) 765 property_set("ro.factorytest", "1"); 766 else if (!strcmp(bootmode,"factory2")) 767 property_set("ro.factorytest", "2"); 768 else 769 property_set("ro.factorytest", "0"); 770 771 property_set("ro.serialno", serialno[0] ? serialno : ""); 772 property_set("ro.bootmode", bootmode[0] ? bootmode : "unknown"); 773 property_set("ro.baseband", baseband[0] ? baseband : "unknown"); 774 property_set("ro.carrier", carrier[0] ? carrier : "unknown"); 775 property_set("ro.bootloader", bootloader[0] ? bootloader : "unknown"); 776 777 property_set("ro.hardware", hardware); 778 snprintf(tmp, PROP_VALUE_MAX, "%d", revision); 779 property_set("ro.revision", tmp); 780 781 /* execute all the boot actions to get us started */ 782 action_for_each_trigger("init", action_add_queue_tail); 783 drain_action_queue(); 784 785 /* read any property files on system or data and 786 * fire up the property service. This must happen 787 * after the ro.foo properties are set above so 788 * that /data/local.prop cannot interfere with them. 789 */ 790 property_set_fd = start_property_service(); 791 792 /* create a signalling mechanism for the sigchld handler */ 793 if (socketpair(AF_UNIX, SOCK_STREAM, 0, s) == 0) { 794 signal_fd = s[0]; 795 signal_recv_fd = s[1]; 796 fcntl(s[0], F_SETFD, FD_CLOEXEC); 797 fcntl(s[0], F_SETFL, O_NONBLOCK); 798 fcntl(s[1], F_SETFD, FD_CLOEXEC); 799 fcntl(s[1], F_SETFL, O_NONBLOCK); 800 } 801 802 /* make sure we actually have all the pieces we need */ 803 if ((device_fd < 0) || 804 (property_set_fd < 0) || 805 (signal_recv_fd < 0)) { 806 ERROR("init startup failure\n"); 807 return 1; 808 } 809 810 /* execute all the boot actions to get us started */ 811 action_for_each_trigger("early-boot", action_add_queue_tail); 812 action_for_each_trigger("boot", action_add_queue_tail); 813 drain_action_queue(); 814 815 /* run all property triggers based on current state of the properties */ 816 queue_all_property_triggers(); 817 drain_action_queue(); 818 819 /* enable property triggers */ 820 property_triggers_enabled = 1; 821 822 ufds[0].fd = device_fd; 823 ufds[0].events = POLLIN; 824 ufds[1].fd = property_set_fd; 825 ufds[1].events = POLLIN; 826 ufds[2].fd = signal_recv_fd; 827 ufds[2].events = POLLIN; 828 829#if BOOTCHART 830 bootchart_count = bootchart_init(); 831 if (bootchart_count < 0) { 832 ERROR("bootcharting init failure\n"); 833 } else if (bootchart_count > 0) { 834 NOTICE("bootcharting started (period=%d ms)\n", bootchart_count*BOOTCHART_POLLING_MS); 835 } else { 836 NOTICE("bootcharting ignored\n"); 837 } 838#endif 839 840 for(;;) { 841 int nr, timeout = -1; 842 843 ufds[0].revents = 0; 844 ufds[1].revents = 0; 845 ufds[2].revents = 0; 846 847 drain_action_queue(); 848 restart_processes(); 849 850 if (process_needs_restart) { 851 timeout = (process_needs_restart - gettime()) * 1000; 852 if (timeout < 0) 853 timeout = 0; 854 } 855 856#if BOOTCHART 857 if (bootchart_count > 0) { 858 if (timeout < 0 || timeout > BOOTCHART_POLLING_MS) 859 timeout = BOOTCHART_POLLING_MS; 860 if (bootchart_step() < 0 || --bootchart_count == 0) { 861 bootchart_finish(); 862 bootchart_count = 0; 863 } 864 } 865#endif 866 nr = poll(ufds, 3, timeout); 867 if (nr <= 0) 868 continue; 869 870 if (ufds[2].revents == POLLIN) { 871 /* we got a SIGCHLD - reap and restart as needed */ 872 read(signal_recv_fd, tmp, sizeof(tmp)); 873 while (!wait_for_one_process(0)) 874 ; 875 continue; 876 } 877 878 if (ufds[0].revents == POLLIN) 879 handle_device_fd(device_fd); 880 881 if (ufds[1].revents == POLLIN) 882 handle_property_set_fd(property_set_fd); 883 } 884 885 return 0; 886} 887