]> git.ipfire.org Git - thirdparty/lldpd.git/commitdiff
priv: monitor the monitor process
authorVincent Bernat <vincent@bernat.im>
Wed, 18 Mar 2015 13:20:26 +0000 (14:20 +0100)
committerVincent Bernat <vincent@bernat.im>
Wed, 18 Mar 2015 13:20:26 +0000 (14:20 +0100)
By monitoring the socket connection with the monitor process, we ensure
that we kill ourselves if the monitor disappears and fails to notice us.

This doesn't work yet because there is no "end of file" event for a
SOCK_DGRAM. See the next commit.

src/daemon/event.c
src/daemon/lldpd.h
src/daemon/privsep_io.c

index 314d71b91d62ab74716a191b7d581cae4521841d..d575b991f27e0960d5c799b181ec357bc40dd24b 100644 (file)
@@ -382,6 +382,42 @@ accept_failed:
        levent_ctl_free_client(client);
 }
 
+static void
+levent_priv(evutil_socket_t fd, short what, void *arg)
+{
+       struct event_base *base = arg;
+       ssize_t n;
+       int err;
+       char one;
+       (void)what;
+       /* Check if we have some data available. We need to pass the socket in
+        * non-blocking mode to be able to run the check without disruption. */
+       levent_make_socket_nonblocking(fd);
+       n = read(fd, &one, 0); err = errno;
+       levent_make_socket_blocking(fd);
+
+       switch (n) {
+       case -1:
+               if (err == EAGAIN || err == EWOULDBLOCK)
+                       /* No data, all good */
+                       return;
+               log_warnx("event", "unable to poll monitor process, exit");
+               break;
+       case 0:
+               log_warnx("event", "monitor process has terminated, exit");
+               break;
+       default:
+               /* Unfortunately, dead code, if we have data, we have requested
+                * 0 byte, so we will fall in the previous case. It seems safer
+                * to ask for 0 byte than asking for 1 byte. In the later case,
+                * if we have to speak with the monitor again before exiting, we
+                * would be out of sync. */
+               log_warnx("event", "received unexpected data from monitor process, exit");
+               break;
+       }
+       event_base_loopbreak(base);
+}
+
 static void
 levent_dump(evutil_socket_t fd, short what, void *arg)
 {
@@ -471,6 +507,14 @@ levent_init(struct lldpd *cfg)
                fatalx("event", "unable to setup control socket event");
        event_add(ctl_event, NULL);
 
+       /* Somehow monitor the monitor process */
+       struct event *monitor_event;
+       log_debug("event", "monitor the monitor process");
+       if ((monitor_event = event_new(cfg->g_base, priv_fd(PRIV_UNPRIVILEGED),
+                   EV_READ|EV_PERSIST, levent_priv, cfg->g_base)) == NULL)
+               fatalx("event", "unable to monitor monitor process");
+       event_add(monitor_event, NULL);
+
        /* Signals */
        log_debug("event", "register signals");
        evsignal_add(evsignal_new(cfg->g_base, SIGUSR1,
@@ -788,3 +832,19 @@ levent_make_socket_nonblocking(int fd)
        }
        return 0;
 }
+
+int
+levent_make_socket_blocking(int fd)
+{
+       int flags;
+       if ((flags = fcntl(fd, F_GETFL, NULL)) < 0) {
+               log_warn("event", "fcntl(%d, F_GETFL)", fd);
+               return -1;
+       }
+       if (!(flags & O_NONBLOCK)) return 0;
+       if (fcntl(fd, F_SETFL, flags & ~O_NONBLOCK) == -1) {
+               log_warn("event", "fcntl(%d, F_SETFL)", fd);
+               return -1;
+       }
+       return 0;
+}
index aea2b716f5d1abef203f9dd542daf3775a727323..c93128ad2f85da2067b142fd4a705e8064deaade 100644 (file)
@@ -157,6 +157,7 @@ int  levent_iface_subscribe(struct lldpd *, int);
 void    levent_schedule_pdu(struct lldpd_hardware *);
 void    levent_schedule_cleanup(struct lldpd *);
 int     levent_make_socket_nonblocking(int);
+int     levent_make_socket_blocking(int);
 
 /* lldp.c */
 int     lldp_send_shutdown(PROTO_SEND_SIG);
@@ -268,6 +269,7 @@ void         must_read(enum priv_context, void *, size_t);
 void    must_write(enum priv_context, const void *, size_t);
 void    priv_privileged_fd(int);
 void    priv_unprivileged_fd(int);
+int     priv_fd(enum priv_context);
 int     receive_fd(enum priv_context);
 void    send_fd(enum priv_context, int);
 
index 39a66be8abadcad48e3f31cf4b7ff65451567dd6..59187919ff0da6db2fa0ad25074ead83f5673b7e 100644 (file)
@@ -26,7 +26,7 @@ priv_unprivileged_fd(int fd)
 {
        unprivileged = fd;
 }
-static int
+int
 priv_fd(enum priv_context ctx)
 {
        switch (ctx) {