void broadcasting_signal(int signo) { for (int i = 0; i < command_line_list->num_of_elements; i++) { command_line* cmd_line = (command_line*)command_line_list->elements[i]; kill_and_wait(cmd_line->pid, signo); } }
/** @todo Possibility to alter priority of initial module somehow */ int main(int argc, char *argv[]) { fprintf(stderr, "DSME %s starting up\n", STRINGIFY(PRG_VERSION)); // do the first kick right away if (!dsme_wd_init()) { fprintf(stderr, ME "no WD's opened; WD kicking disabled\n"); } dsme_wd_kick(); trap_terminating_signals(); // set up signal handler signal(SIGHUP, signal_handler); signal(SIGINT, signal_handler); signal(SIGTERM, signal_handler); signal(SIGPIPE, signal_handler); signal(SIGCHLD, signal_handler); #ifdef DSME_SYSTEMD_ENABLE signal(SIGUSR1, signal_handler); #endif // protect from oom if (!protect_from_oom()) { fprintf(stderr, ME "Couldn't protect from oom: %s\n", strerror(errno)); } // set priority/niceness (will be inherited) if (setpriority(PRIO_PROCESS, 0, DSME_NICE) == -1) { fprintf(stderr, ME "Couldn't set the priority: %s\n", strerror(errno)); } // set scheduler (will be inherited) struct sched_param sch; memset(&sch, 0, sizeof(sch)); sch.sched_priority = sched_get_priority_max(DSME_HB_SCHEDULER); if (sched_setscheduler(0, DSME_HB_SCHEDULER, &sch) == -1) { fprintf(stderr, ME "Couldn't set the scheduler: %s\n", strerror(errno)); } // lock to ram (will not be inherited) if (mlockall(MCL_CURRENT|MCL_FUTURE) == -1) { fprintf(stderr, ME "Couldn't lock to RAM: %s\n", strerror(errno)); } // parse command line options int daemon = 0; parse_options(argc, argv, &daemon); // daemonize if (daemon && daemonize() == -1) { return EXIT_FAILURE; } // set running directory if (chdir("/") == -1) { fprintf(stderr, ME "chdir failed: %s\n", strerror(errno)); return EXIT_FAILURE; } // open communication pipes int to_child[2]; int from_child[2]; if (pipe(to_child) != 0 || pipe(from_child) != 0) { fprintf(stderr, ME "pipe failed: %s\n", strerror(errno)); return EXIT_FAILURE; } // fork and exec the dsme server pid_t pid; if ((pid = fork()) == -1) { fprintf(stderr, ME "fork failed: %s\n", strerror(errno)); return EXIT_FAILURE; } else if (pid == 0) { // child // TODO: lower priority // TODO: restore scheduler // child gets the pipes in stdin & stdout if (dup2(to_child[0], STDIN_FILENO) != STDIN_FILENO) { fprintf(stderr, ME "dup2 failed: %s\n", strerror(errno)); _exit(EXIT_FAILURE); } if (dup2(from_child[1], STDOUT_FILENO) != STDOUT_FILENO) { fprintf(stderr, ME "dup2 failed: %s\n", strerror(errno)); _exit(EXIT_FAILURE); } // close all the other descriptors int max_fd_count = getdtablesize(); if (max_fd_count == -1) { max_fd_count = 256; } for (int i = 3; i < max_fd_count; ++i) { (void)close(i); } // exec dsme server core char* newargv[argc+1]; newargv[0] = (char*)DSME_SERVER_PATH; for (int i = 1; i < argc; ++i) { newargv[i] = argv[i]; } newargv[argc] = 0; execv(DSME_SERVER_PATH, newargv); fprintf(stderr, ME "execv failed: %s: %s\n", DSME_SERVER_PATH, strerror(errno)); _exit(EXIT_FAILURE); } else { // parent // close child ends of pipes & set parent ends of pipes non-blocking close(to_child[0]); close(from_child[1]); set_nonblocking(to_child[1]); set_nonblocking(from_child[0]); } /* Before entering the mainloop, clear wakelock that might be set if dsme * is restarting after signal / watchdog pingpong failure */ release_restart_wakelock(); unsigned sleep_interval = DSME_HEARTBEAT_INTERVAL; mainloop(sleep_interval, to_child[1], from_child[0]); fprintf(stderr, ME "Exited main loop, quitting\n"); /* Get wakelock after exiting the mainloop, will be cleared * if we make orderly normal exit */ obtain_restart_wakelock(); /* Bring down the dsme-server child process * * Note: The maximum duration we can spend here must be shorter * than both hw watchdog kick period and the time systemd * allows for dsme itself to exit. */ // kick watchdogs so we have time to wait for dsme-server to exit dsme_wd_kick(); if( kill_and_wait(pid, SIGTERM, 8) || kill_and_wait(pid, SIGKILL, 3) ) { // clear nowayout states and close watchdog files dsme_wd_quit(); } else { // leave the nowayout states on so that we will get a wd reboot // shortly after dsme exits, but kick the watchdogs one more time // to give the system some time to make orderly shutdown dsme_wd_kick(); fprintf(stderr, ME "dsme-server stop failed, leaving watchdogs" " active\n"); dsme_abnormal_exit = true; } /* Remove the PID file */ if (remove(DSME_PID_FILE) < 0 && errno != ENOENT) { fprintf(stderr, ME "Couldn't remove lockfile: %m\n"); } /* Clear wakelock on normal, successful exit */ if( dsme_abnormal_exit ) fprintf(stderr, ME "abnormal exit, leaving wakelock active\n"); else release_restart_wakelock(); fprintf(stderr, "DSME %s terminating\n", STRINGIFY(PRG_VERSION)); return dsme_abnormal_exit ? EXIT_FAILURE : EXIT_SUCCESS; }