[prev in list] [next in list] [prev in thread] [next in thread]
List: busybox
Subject: [PATCH 7/8] mdev: add SIGHUP handler to reload configuration
From: Jan Klötzke <jan () kloetzke ! net>
Date: 2019-12-16 21:56:55
Message-ID: 20191216215656.6438-8-jan () kloetzke ! net
[Download RAW message or body]
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 <jan@kloetzke.net>
---
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
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic