Lines Matching +full:supervisor +full:- +full:mode

1 /*-
2 * SPDX-License-Identifier: BSD-3-Clause
84 enum daemon_mode mode; member
124 { "change-dir", no_argument, NULL, 'c' },
125 { "close-fds", no_argument, NULL, 'f' },
128 { "output-file", required_argument, NULL, 'o' },
129 { "output-mask", required_argument, NULL, 'm' },
130 { "child-pidfile", required_argument, NULL, 'p' },
131 { "supervisor-pidfile", required_argument, NULL, 'P' },
133 { "restart-count", required_argument, NULL, 'C' },
134 { "restart-delay", required_argument, NULL, 'R' },
137 { "syslog-priority", required_argument, NULL, 's' },
138 { "syslog-facility", required_argument, NULL, 'l' },
139 { "syslog-tag", required_argument, NULL, 'T' },
148 "usage: daemon [-cfHrS] [-p child_pidfile] [-P supervisor_pidfile]\n" in usage()
149 " [-u user] [-o output_file] [-t title]\n" in usage()
150 " [-l syslog_facility] [-s syslog_priority]\n" in usage()
151 " [-T syslog_tag] [-m output_mask] [-R restart_delay_secs]\n" in usage()
152 " [-C restart_count]\n" in usage()
156 " --change-dir -c Change the current working directory to root\n" in usage()
157 " --close-fds -f Set stdin, stdout, stderr to /dev/null\n" in usage()
158 " --sighup -H Close and re-open output file on SIGHUP\n" in usage()
159 " --syslog -S Send output to syslog\n" in usage()
160 " --output-file -o <file> Append output of the child process to file\n" in usage()
161 " --output-mask -m <mask> What to send to syslog/file\n" in usage()
163 " --child-pidfile -p <file> Write PID of the child process to file\n" in usage()
164 " --supervisor-pidfile -P <file> Write PID of the supervisor process to file\n" in usage()
165 " --restart -r Restart child if it terminates (1 sec delay)\n" in usage()
166 " --restart-count -C <N> Restart child at most N times, then exit\n" in usage()
167 " --restart-delay -R <N> Restart child if it terminates after N sec\n" in usage()
168 " --title -t <title> Set the title of the supervisor process\n" in usage()
169 " --user -u <user> Drop privileges, run as given user\n" in usage()
170 " --syslog-priority -s <prio> Set syslog priority\n" in usage()
171 " --syslog-facility -l <flty> Set syslog facility\n" in usage()
172 " --syslog-tag -T <tag> Set syslog tag\n" in usage()
173 " --help -h Show this help\n"); in usage()
192 * Supervision mode is enabled if one of the following options are used: in main()
193 * --child-pidfile -p in main()
194 * --supervisor-pidfile -P in main()
195 * --restart -r / --restart-delay -R in main()
196 * --syslog -S in main()
197 * --syslog-facility -l in main()
198 * --syslog-priority -s in main()
199 * --syslog-tag -T in main()
201 * In supervision mode daemon executes the command in a forked process in main()
202 * and observes the child by waiting for SIGCHILD. In supervision mode in main()
208 while ((ch = getopt_long(argc, argv, shortopts, longopts, NULL)) != -1) { in main()
229 if (state.syslog_facility == -1) { in main()
233 state.mode = MODE_SUPERVISE; in main()
245 * the supervision mode on. For non-supervised mode in main()
249 state.mode = MODE_SUPERVISE; in main()
253 state.mode = MODE_SUPERVISE; in main()
257 state.mode = MODE_SUPERVISE; in main()
261 state.mode = MODE_SUPERVISE; in main()
270 state.mode = MODE_SUPERVISE; in main()
275 if (state.syslog_priority == -1) { in main()
279 state.mode = MODE_SUPERVISE; in main()
283 state.mode = MODE_SUPERVISE; in main()
291 state.mode = MODE_SUPERVISE; in main()
303 argc -= optind; in main()
317 if (state.output_fd == -1) { in main()
335 * i.e. --foreground, -f in main()
337 if (daemon(state.keep_cur_workdir, state.keep_fds_open) == -1) { in main()
342 if (state.mode == MODE_DAEMON) { in main()
352 state.mode = MODE_SUPERVISE; in main()
355 if (state.restart_enabled && state.restart_count > -1) { in main()
369 pidfile_write(state->child_pidfh); in daemon_exec()
371 if (state->user != NULL) { in daemon_exec()
372 restrict_process(state->user); in daemon_exec()
378 execvp(state->argv[0], state->argv); in daemon_exec()
379 /* execvp() failed - report error and exit this process */ in daemon_exec()
380 err(1, "%s", state->argv[0]); in daemon_exec()
386 * - read until EOF
387 * - read until EOF but only for a while
388 * - bail immediately
412 state->pipe_rd = pipe_fd[0]; in daemon_eventloop()
413 state->pipe_wr = pipe_fd[1]; in daemon_eventloop()
415 kq = state->kqueue_fd; in daemon_eventloop()
416 EV_SET(&event, state->pipe_rd, EVFILT_READ, EV_ADD|EV_CLEAR, 0, 0, in daemon_eventloop()
418 if (kevent(kq, &event, 1, NULL, 0, NULL) == -1) { in daemon_eventloop()
425 state->pid = fork(); in daemon_eventloop()
428 switch (state->pid) { in daemon_eventloop()
429 case -1: in daemon_eventloop()
431 state->mode = MODE_NOCHILD; in daemon_eventloop()
442 close(state->pipe_wr); in daemon_eventloop()
443 state->pipe_wr = -1; in daemon_eventloop()
444 setproctitle("%s[%d]", state->title, (int)state->pid); in daemon_eventloop()
447 while (state->mode != MODE_NOCHILD) { in daemon_eventloop()
450 case -1: in daemon_eventloop()
470 state->pid = -1; in daemon_eventloop()
471 state->mode = MODE_NOCHILD; in daemon_eventloop()
478 if (state->mode != MODE_SUPERVISE) { in daemon_eventloop()
484 state->mode = MODE_TERMINATING; in daemon_eventloop()
485 state->restart_enabled = false; in daemon_eventloop()
486 if (state->pid > 0) { in daemon_eventloop()
487 kill(state->pid, SIGTERM); in daemon_eventloop()
495 if (state->log_reopen && state->output_fd >= 0) { in daemon_eventloop()
520 close(state->pipe_rd); in daemon_eventloop()
521 state->pipe_rd = -1; in daemon_eventloop()
528 if (state->child_pidfh != NULL && state->restart_enabled) { in daemon_eventloop()
529 pidfile_truncate(state->child_pidfh); in daemon_eventloop()
543 assert(state->pipe_rd == -1); in daemon_sleep()
544 assert(state->pipe_wr == -1); in daemon_sleep()
546 if (!state->restart_enabled) { in daemon_sleep()
551 state->restart_delay, NULL); in daemon_sleep()
552 if (kevent(state->kqueue_fd, &event, 1, NULL, 0, NULL) == -1) { in daemon_sleep()
557 ret = kevent(state->kqueue_fd, NULL, 0, &event, 1, NULL); in daemon_sleep()
558 if (ret == -1) { in daemon_sleep()
586 state->restart_enabled = false; in daemon_sleep()
589 if (state->log_reopen && state->output_fd >= 0) { in daemon_sleep()
602 assert(state->restart_enabled); in daemon_sleep()
611 if (state->child_pidfile) { in open_pid_files()
612 state->child_pidfh = pidfile_open(state->child_pidfile, 0600, &fpid); in open_pid_files()
613 if (state->child_pidfh == NULL) { in open_pid_files()
618 err(2, "pidfile ``%s''", state->child_pidfile); in open_pid_files()
622 if (state->parent_pidfile) { in open_pid_files()
623 state->parent_pidfh= pidfile_open(state->parent_pidfile, 0600, &fpid); in open_pid_files()
624 if (state->parent_pidfh == NULL) { in open_pid_files()
626 pidfile_remove(state->child_pidfh); in open_pid_files()
632 err(2, "ppidfile ``%s''", state->parent_pidfile); in open_pid_files()
641 for (cp = c; cp->c_name; cp++) in get_log_mapping()
642 if (strcmp(cp->c_name, str) == 0) { in get_log_mapping()
643 return cp->c_val; in get_log_mapping()
645 return -1; in get_log_mapping()
658 if (setusercontext(NULL, pw, pw->pw_uid, LOGIN_SETALL) != 0) { in restrict_process()
662 setenv("USER", pw->pw_name, 1); in restrict_process()
663 setenv("HOME", pw->pw_dir, 1); in restrict_process()
664 setenv("SHELL", *pw->pw_shell ? pw->pw_shell : _PATH_BSHELL, 1); in restrict_process()
681 assert(state->pos < LBUF_SIZE - 1); in listen_child()
683 rv = read(state->pipe_rd, state->buf + state->pos, in listen_child()
684 LBUF_SIZE - state->pos - 1); in listen_child()
686 state->pos += rv; in listen_child()
687 assert(state->pos <= LBUF_SIZE - 1); in listen_child()
688 /* Always NUL-terminate just in case. */ in listen_child()
689 state->buf[LBUF_SIZE - 1] = '\0'; in listen_child()
698 cp = memrchr(state->buf, '\n', state->pos); in listen_child()
700 size_t bytes_line = cp - state->buf + 1; in listen_child()
701 assert(bytes_line <= state->pos); in listen_child()
702 do_output(state->buf, bytes_line, state); in listen_child()
703 state->pos -= bytes_line; in listen_child()
704 memmove(state->buf, cp + 1, state->pos); in listen_child()
707 if (state->pos < LBUF_SIZE - 1) { in listen_child()
710 do_output(state->buf, state->pos, state); in listen_child()
711 state->pos = 0; in listen_child()
713 } else if (rv == -1) { in listen_child()
723 if (state->pos > 0) { in listen_child()
724 do_output(state->buf, state->pos, state); in listen_child()
725 state->pos = 0; in listen_child()
744 if (state->syslog_enabled) { in do_output()
745 syslog(state->syslog_priority, "%.*s", (int)len, buf); in do_output()
747 if (state->output_fd != -1) { in do_output()
748 if (write(state->output_fd, buf, len) == -1) in do_output()
751 if (state->keep_fds_open && in do_output()
752 !state->syslog_enabled && in do_output()
753 state->output_fd == -1) { in do_output()
770 outfd = open_log(state->output_filename); in reopen_log()
771 if (state->output_fd >= 0) { in reopen_log()
772 close(state->output_fd); in reopen_log()
774 state->output_fd = outfd; in reopen_log()
790 .mode = MODE_DAEMON, in daemon_state_init()
793 .pipe_rd = -1, in daemon_state_init()
794 .pipe_wr = -1, in daemon_state_init()
796 .kqueue_fd = -1, in daemon_state_init()
805 .output_fd = -1, in daemon_state_init()
807 .restart_count = -1, in daemon_state_init()
817 if (state->kqueue_fd >= 0) { in daemon_terminate()
818 close(state->kqueue_fd); in daemon_terminate()
820 if (state->output_fd >= 0) { in daemon_terminate()
821 close(state->output_fd); in daemon_terminate()
823 if (state->pipe_rd >= 0) { in daemon_terminate()
824 close(state->pipe_rd); in daemon_terminate()
827 if (state->pipe_wr >= 0) { in daemon_terminate()
828 close(state->pipe_wr); in daemon_terminate()
830 if (state->syslog_enabled) { in daemon_terminate()
833 pidfile_remove(state->child_pidfh); in daemon_terminate()
834 pidfile_remove(state->parent_pidfh); in daemon_terminate()
845 * Returns true if SIGCHILD came from state->pid due to its exit.
853 int who = waitpid(-1, &status, WNOHANG); in daemon_is_child_dead()
854 if (state->pid == who && (WIFEXITED(status) || in daemon_is_child_dead()
861 if (who == -1 && errno != EINTR) { in daemon_is_child_dead()
871 if (state->stdmask & STDERR_FILENO) { in daemon_set_child_pipe()
872 if (dup2(state->pipe_wr, STDERR_FILENO) == -1) { in daemon_set_child_pipe()
876 if (state->stdmask & STDOUT_FILENO) { in daemon_set_child_pipe()
877 if (dup2(state->pipe_wr, STDOUT_FILENO) == -1) { in daemon_set_child_pipe()
881 if (state->pipe_wr != STDERR_FILENO && in daemon_set_child_pipe()
882 state->pipe_wr != STDOUT_FILENO) { in daemon_set_child_pipe()
883 close(state->pipe_wr); in daemon_set_child_pipe()
887 close(state->pipe_rd); in daemon_set_child_pipe()
897 if (kq == -1) { in daemon_setup_kqueue()
902 if (kevent(kq, &event, 1, NULL, 0, NULL) == -1) { in daemon_setup_kqueue()
907 if (kevent(kq, &event, 1, NULL, 0, NULL) == -1) { in daemon_setup_kqueue()
912 if (kevent(kq, &event, 1, NULL, 0, NULL) == -1) { in daemon_setup_kqueue()
926 if (ftruncate(pfd, 0) == -1) in pidfile_truncate()
927 return (-1); in pidfile_truncate()
931 * it may not always and do a best-effort reset of the position just to in pidfile_truncate()