static int script_run(struct script *script) { sigset_t mask, old_mask; siginfo_t info; pid_t pid, *pids; int i, num_commands, status, ret = 0; for (num_commands = 0; script->commands[num_commands]; num_commands++) ; if (!num_commands) { /* nothing to do */ return 0; } if (create_config_files(script->configs)) return 1; sigemptyset(&mask); sigaddset(&mask, SIGCHLD); sigaddset(&mask, SIGTERM); sigaddset(&mask, SIGQUIT); sigaddset(&mask, SIGINT); /* block the signals */ if (sigprocmask(SIG_BLOCK, &mask, &old_mask) < 0) { pr_err("sigprocmask() failed: %m"); return 1; } pids = xcalloc(num_commands, sizeof(*pids)); for (i = 0; i < num_commands; i++) { pids[i] = start_program(script->commands[i], &old_mask); if (!pids[i]) { kill(getpid(), SIGTERM); break; } } /* wait for one of the blocked signals */ while (1) { if (sigwaitinfo(&mask, &info) < 0) { if (errno == EINTR) continue; pr_err("sigwaitinfo() failed: %m"); break; } /* * assume only the first process (i.e. chronyd or ntpd) is * essential and continue if other processes terminate */ if (info.si_signo == SIGCHLD && info.si_pid != pids[0]) { pr_info("process %d terminated (ignored)", info.si_pid); continue; } pr_info("received signal %d", info.si_signo); break; } /* kill all started processes */ for (i = 0; i < num_commands; i++) { if (pids[i] > 0) { pr_debug("killing process %d", pids[i]); kill(pids[i], SIGTERM); } } while ((pid = wait(&status)) >= 0) { if (!WIFEXITED(status)) { pr_info("process %d terminated abnormally", pid); ret = 1; } else { if (WEXITSTATUS(status)) ret = 1; pr_info("process %d terminated with status %d", pid, WEXITSTATUS(status)); } } free(pids); if (remove_config_files(script->configs)) return 1; return ret; }
static int script_run(struct script *script) { sigset_t mask, old_mask; siginfo_t info; pid_t pid, *pids; int i, num_commands, status, ret = 0; if (create_config_files(script->configs)) return 1; sigemptyset(&mask); sigaddset(&mask, SIGCHLD); sigaddset(&mask, SIGTERM); sigaddset(&mask, SIGQUIT); sigaddset(&mask, SIGINT); /* block the signals */ if (sigprocmask(SIG_BLOCK, &mask, &old_mask) < 0) { pr_err("sigprocmask() failed: %m"); return 1; } for (num_commands = 0; script->commands[num_commands]; num_commands++) ; pids = calloc(num_commands, sizeof(*pids)); for (i = 0; i < num_commands; i++) { pids[i] = start_program(script->commands[i], &old_mask); if (!pids[i]) { kill(getpid(), SIGTERM); break; } } /* wait for one of the blocked signals */ while (1) { if (sigwaitinfo(&mask, &info) > 0) break; if (errno != EINTR) { pr_err("sigwaitinfo() failed: %m"); break; } } pr_info("received signal %d", info.si_signo); /* kill all started processes */ for (i = 0; i < num_commands; i++) { if (pids[i] > 0) { pr_debug("killing process %d", pids[i]); kill(pids[i], SIGTERM); } } while ((pid = wait(&status)) >= 0) { if (!WIFEXITED(status)) { pr_info("process %d terminated abnormally", pid); ret = 1; } else { if (WEXITSTATUS(status)) ret = 1; pr_info("process %d terminated with status %d", pid, WEXITSTATUS(status)); } } free(pids); if (remove_config_files(script->configs)) return 1; return ret; }