Like a well behaved daemon the reception of SIGHUP triggers a reload of /etc/mdev.conf. The file is parsed immediately to catch any errors early and to cache the current version.
Signed-off-by: Jan Klötzke <[email protected]> --- util-linux/mdev.c | 106 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 86 insertions(+), 20 deletions(-) diff --git a/util-linux/mdev.c b/util-linux/mdev.c index 671221af5..81c4336af 100644 --- a/util-linux/mdev.c +++ b/util-linux/mdev.c @@ -314,6 +314,10 @@ struct globals { #endif struct rule cur_rule; char timestr[sizeof("HH:MM:SS.123456")]; +#if ENABLE_FEATURE_MDEV_DAEMON + int netlink_fd; + struct fd_pair signal_pipe; +#endif } FIX_ALIASING; #define G (*(struct globals*)bb_common_bufsiz1) #define INIT_G() do { \ @@ -1160,6 +1164,15 @@ static void initial_scan(char *temp) #if ENABLE_FEATURE_MDEV_DAEMON +static void daemon_sighandler(int sig) +{ + int olderrno = errno; + unsigned char ch = sig; /* use char, avoid dealing with partial writes */ + if (write(G.signal_pipe.wr, &ch, 1) != 1) + bb_simple_perror_msg("can't send signal"); + errno = olderrno; +} + /* * The kernel (as of v5.4) will pass up to 32 environment variables with a * total of 2kiB on each event. On top of that the action string and device @@ -1177,10 +1190,8 @@ static void initial_scan(char *temp) # define RCVBUF (128 * 1024 * 1024) # define MAX_ENV 32 -static int daemon_init(char *temp) +static void daemon_init(char *temp) { - int fd; - /* Subscribe for UEVENT kernel messages */ /* Without a sufficiently big RCVBUF, a ton of simultaneous events * can trigger ENOBUFS on read, which is unrecoverable. @@ -1188,7 +1199,9 @@ static int daemon_init(char *temp) * mdev -d * find /sys -name uevent -exec sh -c 'echo add >"{}"' ';' */ - fd = create_and_bind_to_netlink(NETLINK_KOBJECT_UEVENT, 1 << 0, RCVBUF); + G.netlink_fd = create_and_bind_to_netlink(NETLINK_KOBJECT_UEVENT, + 1 << 0, RCVBUF); + ndelay_on(G.netlink_fd); /* * Make inital scan after the uevent socket is alive and @@ -1196,29 +1209,53 @@ static int daemon_init(char *temp) * in daemon mode. */ initial_scan(temp); +} + +static void daemon_handle_sighup(void) +{ + unsigned char sig; + + while (safe_read(G.signal_pipe.rd, &sig, 1) == 1); + +#if ENABLE_FEATURE_MDEV_CONF + // reset parser state + G.filename = "/etc/mdev.conf"; + if (G.parser) { + config_close(G.parser); + G.parser = NULL; + } + G.rule_idx = 0; - return fd; + // parse whole file to flag errors immediately + dbg1("SIGHUP: reload '%s'", G.filename); + do { + next_rule(); + } while (G.parser); +#endif } -static void daemon_loop(char *temp, int fd) +static void daemon_handle_events(char *temp) { - for (;;) { - char netbuf[BUFFER_SIZE]; - char *env[MAX_ENV]; - char *s, *end; - ssize_t len; - int idx; + char netbuf[BUFFER_SIZE]; + char *env[MAX_ENV]; + char *s, *end; + ssize_t len; + int idx; - len = safe_read(fd, netbuf, sizeof(netbuf) - 1); + for (;;) { + len = safe_read(G.netlink_fd, netbuf, sizeof(netbuf) - 1); if (len < 0) { - if (errno == ENOBUFS) { + if (errno == EAGAIN || errno == EWOULDBLOCK) { + // done reading events + break; + } else if (errno == ENOBUFS) { /* * We ran out of socket receive buffer space. * Start from scratch. */ dbg1s("uevent overrun! Rescanning..."); - close(fd); - fd = daemon_init(temp); + close(G.netlink_fd); + daemon_init(temp); continue; } bb_simple_perror_msg_and_die("read"); @@ -1242,6 +1279,37 @@ static void daemon_loop(char *temp, int fd) bb_unsetenv(env[--idx]); } } + +static void daemon_loop(char *temp) +{ + xpiped_pair(G.signal_pipe); + close_on_exec_on(G.signal_pipe.rd); + close_on_exec_on(G.signal_pipe.wr); + ndelay_on(G.signal_pipe.rd); + ndelay_on(G.signal_pipe.wr); + bb_signals((1 << SIGHUP), daemon_sighandler); + + for (;;) { + struct pollfd pfds[2]; + int ret; + + pfds[0].fd = G.netlink_fd; + pfds[0].events = POLLIN; + pfds[1].fd = G.signal_pipe.rd; + pfds[1].events = POLLIN; + ret = poll(pfds, 2, -1); + if (ret <= 0) { + if (ret < 0 && errno != EINTR) + bb_simple_perror_msg_and_die("poll"); + continue; + } + + if (pfds[0].revents) + daemon_handle_events(temp); + if (pfds[1].revents) + daemon_handle_sighup(); + } +} #endif int mdev_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; @@ -1297,12 +1365,10 @@ int mdev_main(int argc UNUSED_PARAM, char **argv) * after initial scan so that caller can be sure everything * is up-to-date when mdev process returns. */ - int fd = daemon_init(temp); - + daemon_init(temp); if (!(opt & MDEV_OPT_FOREGROUND)) bb_daemonize_or_rexec(0, argv); - - daemon_loop(temp, fd); + daemon_loop(temp); } #endif if (opt & MDEV_OPT_SCAN) { -- 2.20.1 _______________________________________________ busybox mailing list [email protected] http://lists.busybox.net/mailman/listinfo/busybox
