#include <sys/un.h>
#include <unistd.h>
+#include "sd-event.h"
+
#include "alloc-util.h"
#include "fd-util.h"
#include "format-util.h"
/* wire protocol magic must match */
#define UDEV_CTRL_MAGIC 0xdead1dea
-enum udev_ctrl_msg_type {
- UDEV_CTRL_UNKNOWN,
- UDEV_CTRL_SET_LOG_LEVEL,
- UDEV_CTRL_STOP_EXEC_QUEUE,
- UDEV_CTRL_START_EXEC_QUEUE,
- UDEV_CTRL_RELOAD,
- UDEV_CTRL_SET_ENV,
- UDEV_CTRL_SET_CHILDREN_MAX,
- UDEV_CTRL_PING,
- UDEV_CTRL_EXIT,
-};
-
struct udev_ctrl_msg_wire {
char version[16];
unsigned magic;
enum udev_ctrl_msg_type type;
- union {
- int intval;
- char buf[256];
- };
-};
-
-struct udev_ctrl_msg {
- unsigned n_ref;
- struct udev_ctrl_connection *conn;
- struct udev_ctrl_msg_wire ctrl_msg_wire;
+ union udev_ctrl_msg_value value;
};
struct udev_ctrl {
unsigned n_ref;
int sock;
+ int sock_connect;
union sockaddr_union saddr;
socklen_t addrlen;
- bool bound;
- bool cleanup_socket;
- bool connected;
-};
-
-struct udev_ctrl_connection {
- unsigned n_ref;
- struct udev_ctrl *uctrl;
- int sock;
+ bool bound:1;
+ bool cleanup_socket:1;
+ bool connected:1;
+ sd_event *event;
+ sd_event_source *event_source;
+ sd_event_source *event_source_connect;
+ udev_ctrl_handler_t callback;
+ void *userdata;
};
int udev_ctrl_new_from_fd(struct udev_ctrl **ret, int fd) {
return 0;
}
+static void udev_ctrl_disconnect(struct udev_ctrl *uctrl) {
+ if (!uctrl)
+ return;
+
+ uctrl->event_source_connect = sd_event_source_unref(uctrl->event_source_connect);
+ uctrl->sock_connect = safe_close(uctrl->sock_connect);
+}
+
static struct udev_ctrl *udev_ctrl_free(struct udev_ctrl *uctrl) {
assert(uctrl);
+ udev_ctrl_disconnect(uctrl);
+
+ sd_event_source_unref(uctrl->event_source);
safe_close(uctrl->sock);
+
+ sd_event_unref(uctrl->event);
return mfree(uctrl);
}
-DEFINE_PRIVATE_TRIVIAL_REF_FUNC(struct udev_ctrl, udev_ctrl);
-DEFINE_TRIVIAL_UNREF_FUNC(struct udev_ctrl, udev_ctrl, udev_ctrl_free);
+DEFINE_TRIVIAL_REF_UNREF_FUNC(struct udev_ctrl, udev_ctrl, udev_ctrl_free);
int udev_ctrl_cleanup(struct udev_ctrl *uctrl) {
if (!uctrl)
return 0;
}
-int udev_ctrl_get_fd(struct udev_ctrl *uctrl) {
- if (!uctrl)
- return -EINVAL;
- return uctrl->sock;
+int udev_ctrl_attach_event(struct udev_ctrl *uctrl, sd_event *event) {
+ int r;
+
+ assert_return(uctrl, -EINVAL);
+ assert_return(!uctrl->event, -EBUSY);
+
+ if (event)
+ uctrl->event = sd_event_ref(event);
+ else {
+ r = sd_event_default(&uctrl->event);
+ if (r < 0)
+ return r;
+ }
+
+ return 0;
}
-struct udev_ctrl_connection *udev_ctrl_get_connection(struct udev_ctrl *uctrl) {
- struct udev_ctrl_connection *conn;
- struct ucred ucred = {};
+sd_event_source *udev_ctrl_get_event_source(struct udev_ctrl *uctrl) {
+ assert(uctrl);
+
+ return uctrl->event_source;
+}
+
+static void udev_ctrl_disconnect_and_listen_again(struct udev_ctrl *uctrl) {
+ udev_ctrl_disconnect(uctrl);
+ udev_ctrl_unref(uctrl);
+ (void) sd_event_source_set_enabled(uctrl->event_source, SD_EVENT_ON);
+}
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_ctrl *, udev_ctrl_disconnect_and_listen_again);
+
+static int udev_ctrl_connection_event_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
+ _cleanup_(udev_ctrl_disconnect_and_listen_againp) struct udev_ctrl *uctrl = NULL;
+ struct udev_ctrl_msg_wire msg_wire;
+ struct iovec iov = IOVEC_MAKE(&msg_wire, sizeof(struct udev_ctrl_msg_wire));
+ char cred_msg[CMSG_SPACE(sizeof(struct ucred))];
+ struct msghdr smsg = {
+ .msg_iov = &iov,
+ .msg_iovlen = 1,
+ .msg_control = cred_msg,
+ .msg_controllen = sizeof(cred_msg),
+ };
+ struct cmsghdr *cmsg;
+ struct ucred *cred;
+ ssize_t size;
+
+ assert(userdata);
+
+ /* When UDEV_CTRL_EXIT is received, manager unref udev_ctrl object.
+ * To avoid the object freed, let's increment the refcount. */
+ uctrl = udev_ctrl_ref(userdata);
+
+ size = next_datagram_size_fd(fd);
+ if (size < 0)
+ return log_error_errno(size, "Failed to get size of message: %m");
+ if (size == 0)
+ return 0; /* Client disconnects? */
+
+ size = recvmsg(fd, &smsg, 0);
+ if (size < 0) {
+ if (errno != EINTR)
+ return log_error_errno(errno, "Failed to receive ctrl message: %m");
+
+ return 0;
+ }
+
+ cmsg_close_all(&smsg);
+
+ cmsg = CMSG_FIRSTHDR(&smsg);
+
+ if (!cmsg || cmsg->cmsg_type != SCM_CREDENTIALS) {
+ log_error("No sender credentials received, ignoring message");
+ return 0;
+ }
+
+ cred = (struct ucred *) CMSG_DATA(cmsg);
+
+ if (cred->uid != 0) {
+ log_error("Invalid sender uid "UID_FMT", ignoring message", cred->uid);
+ return 0;
+ }
+
+ if (msg_wire.magic != UDEV_CTRL_MAGIC) {
+ log_error("Message magic 0x%08x doesn't match, ignoring message", msg_wire.magic);
+ return 0;
+ }
+
+ if (uctrl->callback)
+ (void) uctrl->callback(uctrl, msg_wire.type, &msg_wire.value, uctrl->userdata);
+
+ return 0;
+}
+
+static int udev_ctrl_event_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
+ struct udev_ctrl *uctrl = userdata;
+ _cleanup_close_ int sock = -1;
+ struct ucred ucred;
int r;
- conn = new(struct udev_ctrl_connection, 1);
- if (!conn)
- return NULL;
- conn->n_ref = 1;
- conn->uctrl = uctrl;
+ assert(uctrl);
- conn->sock = accept4(uctrl->sock, NULL, NULL, SOCK_CLOEXEC|SOCK_NONBLOCK);
- if (conn->sock < 0) {
+ sock = accept4(fd, NULL, NULL, SOCK_CLOEXEC|SOCK_NONBLOCK);
+ if (sock < 0) {
if (errno != EINTR)
- log_error_errno(errno, "Failed to receive ctrl connection: %m");
- goto err;
+ log_error_errno(errno, "Failed to accept ctrl connection: %m");
+ return 0;
}
/* check peer credential of connection */
- r = getpeercred(conn->sock, &ucred);
+ r = getpeercred(sock, &ucred);
if (r < 0) {
log_error_errno(r, "Failed to receive credentials of ctrl connection: %m");
- goto err;
+ return 0;
}
+
if (ucred.uid > 0) {
- log_error("Sender uid="UID_FMT", message ignored", ucred.uid);
- goto err;
+ log_error("Invalid sender uid "UID_FMT", closing connection", ucred.uid);
+ return 0;
}
/* enable receiving of the sender credentials in the messages */
- r = setsockopt_int(conn->sock, SOL_SOCKET, SO_PASSCRED, true);
+ r = setsockopt_int(sock, SOL_SOCKET, SO_PASSCRED, true);
if (r < 0)
- log_warning_errno(r, "Failed to set SO_PASSCRED: %m");
+ log_warning_errno(r, "Failed to set SO_PASSCRED, ignoring: %m");
- udev_ctrl_ref(uctrl);
- return conn;
-err:
- safe_close(conn->sock);
- return mfree(conn);
-}
+ r = sd_event_add_io(uctrl->event, &uctrl->event_source_connect, sock, EPOLLIN, udev_ctrl_connection_event_handler, uctrl);
+ if (r < 0) {
+ log_error_errno(r, "Failed to create event source for udev control connection: %m");
+ return 0;
+ }
+
+ (void) sd_event_source_set_description(uctrl->event_source_connect, "udev-ctrl-connection");
-static struct udev_ctrl_connection *udev_ctrl_connection_free(struct udev_ctrl_connection *conn) {
- assert(conn);
+ /* Do not accept multiple connection. */
+ (void) sd_event_source_set_enabled(uctrl->event_source, SD_EVENT_OFF);
- safe_close(conn->sock);
- udev_ctrl_unref(conn->uctrl);
- return mfree(conn);
+ uctrl->sock_connect = TAKE_FD(sock);
+ return 0;
}
-DEFINE_TRIVIAL_REF_UNREF_FUNC(struct udev_ctrl_connection, udev_ctrl_connection, udev_ctrl_connection_free);
+int udev_ctrl_start(struct udev_ctrl *uctrl, udev_ctrl_handler_t callback, void *userdata) {
+ int r;
+
+ assert(uctrl);
+
+ if (!uctrl->event) {
+ r = udev_ctrl_attach_event(uctrl, NULL);
+ if (r < 0)
+ return r;
+ }
+
+ r = udev_ctrl_enable_receiving(uctrl);
+ if (r < 0)
+ return r;
+
+ uctrl->callback = callback;
+ uctrl->userdata = userdata;
+
+ r = sd_event_add_io(uctrl->event, &uctrl->event_source, uctrl->sock, EPOLLIN, udev_ctrl_event_handler, uctrl);
+ if (r < 0)
+ return r;
+
+ (void) sd_event_source_set_description(uctrl->event_source, "udev-ctrl");
+
+ return 0;
+}
static int ctrl_send(struct udev_ctrl *uctrl, enum udev_ctrl_msg_type type, int intval, const char *buf, usec_t timeout) {
struct udev_ctrl_msg_wire ctrl_msg_wire = {
};
if (buf)
- strscpy(ctrl_msg_wire.buf, sizeof(ctrl_msg_wire.buf), buf);
+ strscpy(ctrl_msg_wire.value.buf, sizeof(ctrl_msg_wire.value.buf), buf);
else
- ctrl_msg_wire.intval = intval;
+ ctrl_msg_wire.value.intval = intval;
if (!uctrl->connected) {
if (connect(uctrl->sock, &uctrl->saddr.sa, uctrl->addrlen) < 0)
int udev_ctrl_send_exit(struct udev_ctrl *uctrl, usec_t timeout) {
return ctrl_send(uctrl, UDEV_CTRL_EXIT, 0, NULL, timeout);
}
-
-struct udev_ctrl_msg *udev_ctrl_receive_msg(struct udev_ctrl_connection *conn) {
- struct udev_ctrl_msg *uctrl_msg;
- ssize_t size;
- struct cmsghdr *cmsg;
- struct iovec iov;
- char cred_msg[CMSG_SPACE(sizeof(struct ucred))];
- struct msghdr smsg = {
- .msg_iov = &iov,
- .msg_iovlen = 1,
- .msg_control = cred_msg,
- .msg_controllen = sizeof(cred_msg),
- };
- struct ucred *cred;
-
- uctrl_msg = new0(struct udev_ctrl_msg, 1);
- if (!uctrl_msg)
- return NULL;
- uctrl_msg->n_ref = 1;
- uctrl_msg->conn = conn;
- udev_ctrl_connection_ref(conn);
-
- /* wait for the incoming message */
- for (;;) {
- struct pollfd pfd[1];
- int r;
-
- pfd[0].fd = conn->sock;
- pfd[0].events = POLLIN;
-
- r = poll(pfd, 1, 10000);
- if (r < 0) {
- if (errno == EINTR)
- continue;
- goto err;
- } else if (r == 0) {
- log_error("Timeout waiting for ctrl message");
- goto err;
- } else {
- if (!(pfd[0].revents & POLLIN)) {
- log_error("Invalid ctrl connection: %m");
- goto err;
- }
- }
-
- break;
- }
-
- iov = IOVEC_MAKE(&uctrl_msg->ctrl_msg_wire, sizeof(struct udev_ctrl_msg_wire));
-
- size = recvmsg(conn->sock, &smsg, 0);
- if (size < 0) {
- log_error_errno(errno, "Failed to receive ctrl message: %m");
- goto err;
- }
-
- cmsg_close_all(&smsg);
-
- cmsg = CMSG_FIRSTHDR(&smsg);
-
- if (!cmsg || cmsg->cmsg_type != SCM_CREDENTIALS) {
- log_error("No sender credentials received, ignoring message");
- goto err;
- }
-
- cred = (struct ucred *) CMSG_DATA(cmsg);
-
- if (cred->uid != 0) {
- log_error("Sender uid="UID_FMT", ignoring message", cred->uid);
- goto err;
- }
-
- if (uctrl_msg->ctrl_msg_wire.magic != UDEV_CTRL_MAGIC) {
- log_error("Message magic 0x%08x doesn't match, ignoring", uctrl_msg->ctrl_msg_wire.magic);
- goto err;
- }
-
- return uctrl_msg;
-err:
- udev_ctrl_msg_unref(uctrl_msg);
- return NULL;
-}
-
-static struct udev_ctrl_msg *udev_ctrl_msg_free(struct udev_ctrl_msg *ctrl_msg) {
- assert(ctrl_msg);
-
- udev_ctrl_connection_unref(ctrl_msg->conn);
- return mfree(ctrl_msg);
-}
-
-DEFINE_TRIVIAL_UNREF_FUNC(struct udev_ctrl_msg, udev_ctrl_msg, udev_ctrl_msg_free);
-
-int udev_ctrl_get_set_log_level(struct udev_ctrl_msg *ctrl_msg) {
- if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_SET_LOG_LEVEL)
- return ctrl_msg->ctrl_msg_wire.intval;
- return -1;
-}
-
-int udev_ctrl_get_stop_exec_queue(struct udev_ctrl_msg *ctrl_msg) {
- if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_STOP_EXEC_QUEUE)
- return 1;
- return -1;
-}
-
-int udev_ctrl_get_start_exec_queue(struct udev_ctrl_msg *ctrl_msg) {
- if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_START_EXEC_QUEUE)
- return 1;
- return -1;
-}
-
-int udev_ctrl_get_reload(struct udev_ctrl_msg *ctrl_msg) {
- if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_RELOAD)
- return 1;
- return -1;
-}
-
-const char *udev_ctrl_get_set_env(struct udev_ctrl_msg *ctrl_msg) {
- if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_SET_ENV)
- return ctrl_msg->ctrl_msg_wire.buf;
- return NULL;
-}
-
-int udev_ctrl_get_set_children_max(struct udev_ctrl_msg *ctrl_msg) {
- if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_SET_CHILDREN_MAX)
- return ctrl_msg->ctrl_msg_wire.intval;
- return -1;
-}
-
-int udev_ctrl_get_ping(struct udev_ctrl_msg *ctrl_msg) {
- if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_PING)
- return 1;
- return -1;
-}
-
-int udev_ctrl_get_exit(struct udev_ctrl_msg *ctrl_msg) {
- if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_EXIT)
- return 1;
- return -1;
-}
/* SPDX-License-Identifier: GPL-2.0+ */
#pragma once
+#include "sd-event.h"
+
#include "macro.h"
#include "time-util.h"
struct udev_ctrl;
+enum udev_ctrl_msg_type {
+ UDEV_CTRL_UNKNOWN,
+ UDEV_CTRL_SET_LOG_LEVEL,
+ UDEV_CTRL_STOP_EXEC_QUEUE,
+ UDEV_CTRL_START_EXEC_QUEUE,
+ UDEV_CTRL_RELOAD,
+ UDEV_CTRL_SET_ENV,
+ UDEV_CTRL_SET_CHILDREN_MAX,
+ UDEV_CTRL_PING,
+ UDEV_CTRL_EXIT,
+};
+
+union udev_ctrl_msg_value {
+ int intval;
+ char buf[256];
+};
+
+typedef int (*udev_ctrl_handler_t)(struct udev_ctrl *udev_ctrl, enum udev_ctrl_msg_type type,
+ const union udev_ctrl_msg_value *value, void *userdata);
+
int udev_ctrl_new_from_fd(struct udev_ctrl **ret, int fd);
static inline int udev_ctrl_new(struct udev_ctrl **ret) {
return udev_ctrl_new_from_fd(ret, -1);
}
int udev_ctrl_enable_receiving(struct udev_ctrl *uctrl);
+struct udev_ctrl *udev_ctrl_ref(struct udev_ctrl *uctrl);
struct udev_ctrl *udev_ctrl_unref(struct udev_ctrl *uctrl);
int udev_ctrl_cleanup(struct udev_ctrl *uctrl);
-int udev_ctrl_get_fd(struct udev_ctrl *uctrl);
+int udev_ctrl_attach_event(struct udev_ctrl *uctrl, sd_event *event);
+int udev_ctrl_start(struct udev_ctrl *uctrl, udev_ctrl_handler_t callback, void *userdata);
+sd_event_source *udev_ctrl_get_event_source(struct udev_ctrl *uctrl);
+
int udev_ctrl_send_set_log_level(struct udev_ctrl *uctrl, int priority, usec_t timeout);
int udev_ctrl_send_stop_exec_queue(struct udev_ctrl *uctrl, usec_t timeout);
int udev_ctrl_send_start_exec_queue(struct udev_ctrl *uctrl, usec_t timeout);
int udev_ctrl_send_set_env(struct udev_ctrl *uctrl, const char *key, usec_t timeout);
int udev_ctrl_send_set_children_max(struct udev_ctrl *uctrl, int count, usec_t timeout);
-struct udev_ctrl_connection;
-struct udev_ctrl_connection *udev_ctrl_get_connection(struct udev_ctrl *uctrl);
-struct udev_ctrl_connection *udev_ctrl_connection_ref(struct udev_ctrl_connection *conn);
-struct udev_ctrl_connection *udev_ctrl_connection_unref(struct udev_ctrl_connection *conn);
-
-struct udev_ctrl_msg;
-struct udev_ctrl_msg *udev_ctrl_receive_msg(struct udev_ctrl_connection *conn);
-struct udev_ctrl_msg *udev_ctrl_msg_unref(struct udev_ctrl_msg *ctrl_msg);
-int udev_ctrl_get_set_log_level(struct udev_ctrl_msg *ctrl_msg);
-int udev_ctrl_get_stop_exec_queue(struct udev_ctrl_msg *ctrl_msg);
-int udev_ctrl_get_start_exec_queue(struct udev_ctrl_msg *ctrl_msg);
-int udev_ctrl_get_reload(struct udev_ctrl_msg *ctrl_msg);
-int udev_ctrl_get_ping(struct udev_ctrl_msg *ctrl_msg);
-int udev_ctrl_get_exit(struct udev_ctrl_msg *ctrl_msg);
-const char *udev_ctrl_get_set_env(struct udev_ctrl_msg *ctrl_msg);
-int udev_ctrl_get_set_children_max(struct udev_ctrl_msg *ctrl_msg);
-
DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_ctrl*, udev_ctrl_unref);
-DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_ctrl_connection*, udev_ctrl_connection_unref);
-DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_ctrl_msg*, udev_ctrl_msg_unref);
sd_device_monitor *monitor;
struct udev_ctrl *ctrl;
- struct udev_ctrl_connection *ctrl_conn_blocking;
int fd_inotify;
int worker_watch[2];
- sd_event_source *ctrl_event;
sd_event_source *inotify_event;
sd_event_source *kill_workers_event;
static void manager_clear_for_worker(Manager *manager) {
assert(manager);
- manager->ctrl_event = sd_event_source_unref(manager->ctrl_event);
manager->inotify_event = sd_event_source_unref(manager->inotify_event);
manager->kill_workers_event = sd_event_source_unref(manager->kill_workers_event);
event_queue_cleanup(manager, EVENT_UNDEF);
manager->monitor = sd_device_monitor_unref(manager->monitor);
- manager->ctrl_conn_blocking = udev_ctrl_connection_unref(manager->ctrl_conn_blocking);
manager->ctrl = udev_ctrl_unref(manager->ctrl);
manager->worker_watch[READ_END] = safe_close(manager->worker_watch[READ_END]);
"STATUS=Starting shutdown...");
/* close sources of new events and discard buffered events */
- manager->ctrl_event = sd_event_source_unref(manager->ctrl_event);
manager->ctrl = udev_ctrl_unref(manager->ctrl);
manager->inotify_event = sd_event_source_unref(manager->inotify_event);
}
/* receive the udevd message from userspace */
-static int on_ctrl_msg(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
+static int on_ctrl_msg(struct udev_ctrl *uctrl, enum udev_ctrl_msg_type type, const union udev_ctrl_msg_value *value, void *userdata) {
Manager *manager = userdata;
- _cleanup_(udev_ctrl_connection_unrefp) struct udev_ctrl_connection *ctrl_conn = NULL;
- _cleanup_(udev_ctrl_msg_unrefp) struct udev_ctrl_msg *ctrl_msg = NULL;
- const char *str;
- int i, r;
+ int r;
+ assert(value);
assert(manager);
- ctrl_conn = udev_ctrl_get_connection(manager->ctrl);
- if (!ctrl_conn)
- return 1;
-
- ctrl_msg = udev_ctrl_receive_msg(ctrl_conn);
- if (!ctrl_msg)
- return 1;
-
- i = udev_ctrl_get_set_log_level(ctrl_msg);
- if (i >= 0) {
- log_debug("Received udev control message (SET_LOG_LEVEL), setting log_priority=%i", i);
- log_set_max_level_realm(LOG_REALM_UDEV, i);
- log_set_max_level_realm(LOG_REALM_SYSTEMD, i);
+ switch (type) {
+ case UDEV_CTRL_SET_LOG_LEVEL:
+ log_debug("Received udev control message (SET_LOG_LEVEL), setting log_priority=%i", value->intval);
+ log_set_max_level_realm(LOG_REALM_UDEV, value->intval);
+ log_set_max_level_realm(LOG_REALM_SYSTEMD, value->intval);
manager_kill_workers(manager);
- }
-
- if (udev_ctrl_get_stop_exec_queue(ctrl_msg) > 0) {
+ break;
+ case UDEV_CTRL_STOP_EXEC_QUEUE:
log_debug("Received udev control message (STOP_EXEC_QUEUE)");
manager->stop_exec_queue = true;
- }
-
- if (udev_ctrl_get_start_exec_queue(ctrl_msg) > 0) {
+ break;
+ case UDEV_CTRL_START_EXEC_QUEUE:
log_debug("Received udev control message (START_EXEC_QUEUE)");
manager->stop_exec_queue = false;
event_queue_start(manager);
- }
-
- if (udev_ctrl_get_reload(ctrl_msg) > 0) {
+ break;
+ case UDEV_CTRL_RELOAD:
log_debug("Received udev control message (RELOAD)");
manager_reload(manager);
- }
-
- str = udev_ctrl_get_set_env(ctrl_msg);
- if (str) {
+ break;
+ case UDEV_CTRL_SET_ENV: {
_cleanup_free_ char *key = NULL, *val = NULL, *old_key = NULL, *old_val = NULL;
- char *eq;
+ const char *eq;
- eq = strchr(str, '=');
+ eq = strchr(value->buf, '=');
if (!eq) {
- log_error("Invalid key format '%s'", str);
+ log_error("Invalid key format '%s'", value->buf);
return 1;
}
- key = strndup(str, eq - str);
+ key = strndup(value->buf, eq - value->buf);
if (!key) {
log_oom();
return 1;
key = val = NULL;
manager_kill_workers(manager);
+ break;
}
+ case UDEV_CTRL_SET_CHILDREN_MAX:
+ if (value->intval <= 0) {
+ log_debug("Received invalid udev control message (SET_MAX_CHILDREN, %i), ignoring.", value->intval);
+ return 0;
+ }
- i = udev_ctrl_get_set_children_max(ctrl_msg);
- if (i >= 0) {
- log_debug("Receivd udev control message (SET_MAX_CHILDREN), setting children_max=%i", i);
- arg_children_max = i;
+ log_debug("Received udev control message (SET_MAX_CHILDREN), setting children_max=%i", value->intval);
+ arg_children_max = value->intval;
(void) sd_notifyf(false,
"READY=1\n"
"STATUS=Processing with %u children at max", arg_children_max);
- }
-
- if (udev_ctrl_get_ping(ctrl_msg) > 0)
+ break;
+ case UDEV_CTRL_PING:
log_debug("Received udev control message (PING)");
-
- if (udev_ctrl_get_exit(ctrl_msg) > 0) {
+ break;
+ case UDEV_CTRL_EXIT:
log_debug("Received udev control message (EXIT)");
manager_exit(manager);
- /* keep reference to block the client until we exit
- TODO: deal with several blocking exit requests */
- manager->ctrl_conn_blocking = udev_ctrl_connection_ref(ctrl_conn);
+ break;
+ default:
+ log_debug("Received unknown udev control message, ignoring");
}
return 1;
}
static int main_loop(Manager *manager) {
- int fd_worker, fd_ctrl, r;
+ int fd_worker, r;
/* unnamed socket from workers to the main daemon */
r = socketpair(AF_LOCAL, SOCK_DGRAM|SOCK_CLOEXEC, 0, manager->worker_watch);
if (r < 0)
return log_error_errno(r, "Failed to create watchdog event source: %m");
- fd_ctrl = udev_ctrl_get_fd(manager->ctrl);
- if (fd_ctrl < 0)
- return log_error_errno(fd_ctrl, "Failed to get udev control socket fd: %m");
+ r = udev_ctrl_attach_event(manager->ctrl, manager->event);
+ if (r < 0)
+ return log_error_errno(r, "Failed to attach event to udev control: %m");
- r = sd_event_add_io(manager->event, &manager->ctrl_event, fd_ctrl, EPOLLIN, on_ctrl_msg, manager);
+ r = udev_ctrl_start(manager->ctrl, on_ctrl_msg, manager);
if (r < 0)
- return log_error_errno(r, "Failed to create udev control event source: %m");
+ return log_error_errno(r, "Failed to start device monitor: %m");
/* This needs to be after the inotify and uevent handling, to make sure
* that the ping is send back after fully processing the pending uevents
* (including the synthetic ones we may create due to inotify events).
*/
- r = sd_event_source_set_priority(manager->ctrl_event, SD_EVENT_PRIORITY_IDLE);
+ r = sd_event_source_set_priority(udev_ctrl_get_event_source(manager->ctrl), SD_EVENT_PRIORITY_IDLE);
if (r < 0)
return log_error_errno(r, "Failed to set IDLE event priority for udev control event source: %m");