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)
{
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,
}
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;
+}
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);
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);