Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F145486892
D47004.id146718.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D47004.id146718.diff
View Options
diff --git a/usr.sbin/daemon/daemon.c b/usr.sbin/daemon/daemon.c
--- a/usr.sbin/daemon/daemon.c
+++ b/usr.sbin/daemon/daemon.c
@@ -86,6 +86,7 @@
int pipe_rd;
int pipe_wr;
int keep_cur_workdir;
+ int kqueue_fd;
int restart_delay;
int stdmask;
int syslog_priority;
@@ -113,6 +114,7 @@
static void daemon_exec(struct daemon_state *);
static bool daemon_is_child_dead(struct daemon_state *);
static void daemon_set_child_pipe(struct daemon_state *);
+static int daemon_setup_kqueue(void);
static int pidfile_truncate(struct pidfh *);
@@ -344,6 +346,8 @@
/* Write out parent pidfile if needed. */
pidfile_write(state.parent_pidfh);
+ state.kqueue_fd = daemon_setup_kqueue();
+
do {
state.mode = MODE_SUPERVISE;
daemon_eventloop(&state);
@@ -408,27 +412,13 @@
state->pipe_rd = pipe_fd[0];
state->pipe_wr = pipe_fd[1];
- kq = kqueuex(KQUEUE_CLOEXEC);
+ kq = state->kqueue_fd;
EV_SET(&event, state->pipe_rd, EVFILT_READ, EV_ADD|EV_CLEAR, 0, 0,
NULL);
if (kevent(kq, &event, 1, NULL, 0, NULL) == -1) {
err(EXIT_FAILURE, "failed to register kevent");
}
- EV_SET(&event, SIGHUP, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
- if (kevent(kq, &event, 1, NULL, 0, NULL) == -1) {
- err(EXIT_FAILURE, "failed to register kevent");
- }
-
- EV_SET(&event, SIGTERM, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
- if (kevent(kq, &event, 1, NULL, 0, NULL) == -1) {
- err(EXIT_FAILURE, "failed to register kevent");
- }
-
- EV_SET(&event, SIGCHLD, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
- if (kevent(kq, &event, 1, NULL, 0, NULL) == -1) {
- err(EXIT_FAILURE, "failed to register kevent");
- }
memset(&event, 0, sizeof(struct kevent));
/* Spawn a child to exec the command. */
@@ -521,11 +511,12 @@
}
continue;
default:
+ assert(0 && "Unexpected kevent filter type");
continue;
}
}
- close(kq);
+ /* EVFILT_READ kqueue filter goes away here. */
close(state->pipe_rd);
state->pipe_rd = -1;
@@ -539,19 +530,76 @@
}
}
+/*
+ * Note that daemon_sleep() should not be called with anything but the signal
+ * events in the kqueue without further consideration.
+ */
static void
daemon_sleep(struct daemon_state *state)
{
- struct timespec ts = { state->restart_delay, 0 };
+ struct kevent event = { 0 };
+ int ret;
+
+ assert(state->pipe_rd == -1);
+ assert(state->pipe_wr == -1);
if (!state->restart_enabled) {
return;
}
- while (nanosleep(&ts, &ts) == -1) {
- if (errno != EINTR) {
- err(1, "nanosleep");
+
+ EV_SET(&event, 0, EVFILT_TIMER, EV_ADD|EV_ONESHOT, NOTE_SECONDS,
+ state->restart_delay, NULL);
+ if (kevent(state->kqueue_fd, &event, 1, NULL, 0, NULL) == -1) {
+ err(1, "failed to register timer");
+ }
+
+ for (;;) {
+ ret = kevent(state->kqueue_fd, NULL, 0, &event, 1, NULL);
+ if (ret == -1) {
+ if (errno != EINTR) {
+ err(1, "kevent");
+ }
+
+ continue;
+ }
+
+ /*
+ * Any other events being raised are indicative of a problem
+ * that we need to investigate. Most likely being that
+ * something was not cleaned up from the eventloop.
+ */
+ assert(event.filter == EVFILT_TIMER ||
+ event.filter == EVFILT_SIGNAL);
+
+ if (event.filter == EVFILT_TIMER) {
+ /* Break's over, back to work. */
+ break;
+ }
+
+ /* Process any pending signals. */
+ switch (event.ident) {
+ case SIGTERM:
+ /*
+ * We could disarm the timer, but we'll be terminating
+ * promptly anyways.
+ */
+ state->restart_enabled = false;
+ return;
+ case SIGHUP:
+ if (state->log_reopen && state->output_fd >= 0) {
+ reopen_log(state);
+ }
+
+ break;
+ case SIGCHLD:
+ default:
+ /* Discard */
+ break;
}
}
+
+ /* SIGTERM should've returned immediately. */
+ assert(state->restart_enabled);
}
static void
@@ -745,6 +793,7 @@
.pipe_rd = -1,
.pipe_wr = -1,
.keep_cur_workdir = 1,
+ .kqueue_fd = -1,
.restart_delay = 1,
.stdmask = STDOUT_FILENO | STDERR_FILENO,
.syslog_enabled = false,
@@ -765,6 +814,9 @@
{
assert(state != NULL);
+ if (state->kqueue_fd >= 0) {
+ close(state->kqueue_fd);
+ }
if (state->output_fd >= 0) {
close(state->output_fd);
}
@@ -835,6 +887,35 @@
close(state->pipe_rd);
}
+static int
+daemon_setup_kqueue(void)
+{
+ int kq;
+ struct kevent event = { 0 };
+
+ kq = kqueuex(KQUEUE_CLOEXEC);
+ if (kq == -1) {
+ err(EXIT_FAILURE, "kqueue");
+ }
+
+ EV_SET(&event, SIGHUP, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
+ if (kevent(kq, &event, 1, NULL, 0, NULL) == -1) {
+ err(EXIT_FAILURE, "failed to register kevent");
+ }
+
+ EV_SET(&event, SIGTERM, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
+ if (kevent(kq, &event, 1, NULL, 0, NULL) == -1) {
+ err(EXIT_FAILURE, "failed to register kevent");
+ }
+
+ EV_SET(&event, SIGCHLD, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
+ if (kevent(kq, &event, 1, NULL, 0, NULL) == -1) {
+ err(EXIT_FAILURE, "failed to register kevent");
+ }
+
+ return (kq);
+}
+
static int
pidfile_truncate(struct pidfh *pfh)
{
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Feb 21, 10:57 AM (4 h, 24 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28921198
Default Alt Text
D47004.id146718.diff (4 KB)
Attached To
Mode
D47004: daemon: stop rebuilding the kqueue every restart of the child
Attached
Detach File
Event Timeline
Log In to Comment