return mfree(manager);
}
-static int on_sigchld(sd_event_source *s, const siginfo_t *si, void *userdata);
-
-static int worker_new(Worker **ret, Manager *manager, sd_device_monitor *worker_monitor, PidRef *pidref) {
- _cleanup_(worker_freep) Worker *worker = NULL;
- int r;
-
- assert(ret);
- assert(manager);
- assert(worker_monitor);
- assert(pidref);
-
- /* This takes and invalidates pidref even on some error cases. */
+Manager* manager_new(void) {
+ Manager *manager;
- worker = new(Worker, 1);
- if (!worker)
- return -ENOMEM;
+ manager = new(Manager, 1);
+ if (!manager)
+ return NULL;
- *worker = (Worker) {
- .pidref = TAKE_PIDREF(*pidref),
+ *manager = (Manager) {
+ .inotify_fd = -EBADF,
+ .config_by_udev_conf = UDEV_CONFIG_INIT,
+ .config_by_command = UDEV_CONFIG_INIT,
+ .config_by_kernel = UDEV_CONFIG_INIT,
+ .config_by_control = UDEV_CONFIG_INIT,
+ .config = UDEV_CONFIG_INIT,
};
- r = device_monitor_get_address(worker_monitor, &worker->address);
- if (r < 0)
- return r;
-
- r = event_add_child_pidref(manager->event, &worker->child_event_source, &worker->pidref, WEXITED, on_sigchld, worker);
- if (r < 0)
- return r;
-
- r = sd_event_source_set_priority(worker->child_event_source, EVENT_PRIORITY_WORKER_SIGCHLD);
- if (r < 0)
- return r;
-
- r = hashmap_ensure_put(&manager->workers, &worker_hash_op, &worker->pidref, worker);
- if (r < 0)
- return r;
-
- worker->manager = manager;
-
- *ret = TAKE_PTR(worker);
- return 0;
+ return manager;
}
void manager_kill_workers(Manager *manager, int signo) {
notify_ready(manager);
}
+static int on_sigchld(sd_event_source *s, const siginfo_t *si, void *userdata) {
+ _cleanup_(worker_freep) Worker *worker = ASSERT_PTR(userdata);
+ sd_device *dev = worker->event ? ASSERT_PTR(worker->event->dev) : NULL;
+ int r;
+
+ assert(si);
+
+ switch (si->si_code) {
+ case CLD_EXITED:
+ if (si->si_status == 0) {
+ log_device_debug(dev, "Worker ["PID_FMT"] exited.", si->si_pid);
+ return 0;
+ }
+
+ log_device_warning(dev, "Worker ["PID_FMT"] exited with return code %i.",
+ si->si_pid, si->si_status);
+ if (!dev)
+ return 0;
+
+ (void) device_add_exit_status(dev, si->si_status);
+ break;
+
+ case CLD_KILLED:
+ case CLD_DUMPED:
+ log_device_warning(dev, "Worker ["PID_FMT"] terminated by signal %i (%s).",
+ si->si_pid, si->si_status, signal_to_string(si->si_status));
+ if (!dev)
+ return 0;
+
+ (void) device_add_signal(dev, si->si_status);
+ break;
+
+ default:
+ assert_not_reached();
+ }
+
+ /* delete state from disk */
+ device_delete_db(dev);
+ device_tag_index(dev, NULL, false);
+
+ r = device_monitor_send(worker->manager->monitor, NULL, dev);
+ if (r < 0)
+ log_device_warning_errno(dev, r, "Failed to broadcast event to libudev listeners, ignoring: %m");
+
+ return 0;
+}
+
+static int worker_new(Worker **ret, Manager *manager, sd_device_monitor *worker_monitor, PidRef *pidref) {
+ _cleanup_(worker_freep) Worker *worker = NULL;
+ int r;
+
+ assert(ret);
+ assert(manager);
+ assert(worker_monitor);
+ assert(pidref);
+
+ /* This takes and invalidates pidref even on some error cases. */
+
+ worker = new(Worker, 1);
+ if (!worker)
+ return -ENOMEM;
+
+ *worker = (Worker) {
+ .pidref = TAKE_PIDREF(*pidref),
+ };
+
+ r = device_monitor_get_address(worker_monitor, &worker->address);
+ if (r < 0)
+ return r;
+
+ r = event_add_child_pidref(manager->event, &worker->child_event_source, &worker->pidref, WEXITED, on_sigchld, worker);
+ if (r < 0)
+ return r;
+
+ r = sd_event_source_set_priority(worker->child_event_source, EVENT_PRIORITY_WORKER_SIGCHLD);
+ if (r < 0)
+ return r;
+
+ r = hashmap_ensure_put(&manager->workers, &worker_hash_op, &worker->pidref, worker);
+ if (r < 0)
+ return r;
+
+ worker->manager = manager;
+
+ *ret = TAKE_PTR(worker);
+ return 0;
+}
+
static int on_event_timeout(sd_event_source *s, uint64_t usec, void *userdata) {
Event *event = ASSERT_PTR(userdata);
return 1;
}
+static int manager_init_device_monitor(Manager *manager, int fd) {
+ int r;
+
+ assert(manager);
+
+ /* This takes passed file descriptor on success. */
+
+ if (fd >= 0) {
+ if (manager->monitor)
+ return log_warning_errno(SYNTHETIC_ERRNO(EALREADY), "Received multiple netlink socket (%i), ignoring.", fd);
+
+ r = sd_is_socket(fd, AF_NETLINK, SOCK_RAW, /* listening = */ -1);
+ if (r < 0)
+ return log_warning_errno(r, "Failed to verify socket type of %i, ignoring: %m", fd);
+ if (r == 0)
+ return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), "Received invalid netlink socket (%i), ignoring.", fd);
+ } else {
+ if (manager->monitor)
+ return 0;
+ }
+
+ r = device_monitor_new_full(&manager->monitor, MONITOR_GROUP_KERNEL, fd);
+ if (r < 0)
+ return log_error_errno(r, "Failed to initialize device monitor: %m");
+
+ return 0;
+}
+
+static int manager_start_device_monitor(Manager *manager) {
+ int r;
+
+ assert(manager);
+
+ r = manager_init_device_monitor(manager, -EBADF);
+ if (r < 0)
+ return r;
+
+ (void) sd_device_monitor_set_description(manager->monitor, "manager");
+
+ r = sd_device_monitor_attach_event(manager->monitor, manager->event);
+ if (r < 0)
+ return log_error_errno(r, "Failed to attach event to device monitor: %m");
+
+ r = sd_device_monitor_start(manager->monitor, on_uevent, manager);
+ if (r < 0)
+ return log_error_errno(r, "Failed to start device monitor: %m");
+
+ r = sd_event_source_set_priority(sd_device_monitor_get_event_source(manager->monitor), EVENT_PRIORITY_DEVICE_MONITOR);
+ if (r < 0)
+ return log_error_errno(r, "Failed to set priority to device monitor: %m");
+
+ return 0;
+}
+
static int on_worker_notify(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
Manager *manager = ASSERT_PTR(userdata);
int r;
return 0;
}
+static int manager_start_worker_notify(Manager *manager) {
+ int r;
+
+ assert(manager);
+ assert(manager->event);
+
+ r = notify_socket_prepare(
+ manager->event,
+ EVENT_PRIORITY_WORKER_NOTIFY,
+ on_worker_notify,
+ manager,
+ &manager->worker_notify_socket_path);
+ if (r < 0)
+ return log_error_errno(r, "Failed to prepare worker notification socket: %m");
+
+ return 0;
+}
+
static int on_sigterm(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
Manager *manager = ASSERT_PTR(userdata);
return 1;
}
-static int on_sigchld(sd_event_source *s, const siginfo_t *si, void *userdata) {
- _cleanup_(worker_freep) Worker *worker = ASSERT_PTR(userdata);
- sd_device *dev = worker->event ? ASSERT_PTR(worker->event->dev) : NULL;
- int r;
-
- assert(si);
-
- switch (si->si_code) {
- case CLD_EXITED:
- if (si->si_status == 0) {
- log_device_debug(dev, "Worker ["PID_FMT"] exited.", si->si_pid);
- return 0;
- }
-
- log_device_warning(dev, "Worker ["PID_FMT"] exited with return code %i.",
- si->si_pid, si->si_status);
- if (!dev)
- return 0;
-
- (void) device_add_exit_status(dev, si->si_status);
- break;
-
- case CLD_KILLED:
- case CLD_DUMPED:
- log_device_warning(dev, "Worker ["PID_FMT"] terminated by signal %i (%s).",
- si->si_pid, si->si_status, signal_to_string(si->si_status));
- if (!dev)
- return 0;
-
- (void) device_add_signal(dev, si->si_status);
- break;
-
- default:
- assert_not_reached();
- }
-
- /* delete state from disk */
- device_delete_db(dev);
- device_tag_index(dev, NULL, false);
-
- r = device_monitor_send(worker->manager->monitor, NULL, dev);
- if (r < 0)
- log_device_warning_errno(dev, r, "Failed to broadcast event to libudev listeners, ignoring: %m");
-
- return 0;
-}
-
static int manager_unlink_queue_file(Manager *manager) {
assert(manager);
return 0;
}
-Manager* manager_new(void) {
- Manager *manager;
-
- manager = new(Manager, 1);
- if (!manager)
- return NULL;
-
- *manager = (Manager) {
- .inotify_fd = -EBADF,
- .config_by_udev_conf = UDEV_CONFIG_INIT,
- .config_by_command = UDEV_CONFIG_INIT,
- .config_by_kernel = UDEV_CONFIG_INIT,
- .config_by_control = UDEV_CONFIG_INIT,
- .config = UDEV_CONFIG_INIT,
- };
-
- return manager;
-}
-
-static int manager_init_device_monitor(Manager *manager, int fd) {
- int r;
-
- assert(manager);
-
- /* This takes passed file descriptor on success. */
-
- if (fd >= 0) {
- if (manager->monitor)
- return log_warning_errno(SYNTHETIC_ERRNO(EALREADY), "Received multiple netlink socket (%i), ignoring.", fd);
-
- r = sd_is_socket(fd, AF_NETLINK, SOCK_RAW, /* listening = */ -1);
- if (r < 0)
- return log_warning_errno(r, "Failed to verify socket type of %i, ignoring: %m", fd);
- if (r == 0)
- return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), "Received invalid netlink socket (%i), ignoring.", fd);
- } else {
- if (manager->monitor)
- return 0;
- }
-
- r = device_monitor_new_full(&manager->monitor, MONITOR_GROUP_KERNEL, fd);
- if (r < 0)
- return log_error_errno(r, "Failed to initialize device monitor: %m");
-
- return 0;
-}
-
-static int manager_listen_fds(Manager *manager) {
- _cleanup_strv_free_ char **names = NULL;
- int r;
-
- assert(manager);
-
- int n = sd_listen_fds_with_names(/* unset_environment = */ true, &names);
- if (n < 0)
- return n;
-
- for (int i = 0; i < n; i++) {
- int fd = SD_LISTEN_FDS_START + i;
-
- if (streq(names[i], "varlink"))
- r = 0; /* The fd will be handled by sd_varlink_server_listen_auto(). */
- else if (streq(names[i], "systemd-udevd-control.socket"))
- r = manager_init_ctrl(manager, fd);
- else if (streq(names[i], "systemd-udevd-kernel.socket"))
- r = manager_init_device_monitor(manager, fd);
- else if (streq(names[i], "inotify"))
- r = manager_init_inotify(manager, fd);
- else
- r = log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
- "Received unexpected fd (%s), ignoring.", names[i]);
- if (r < 0)
- close_and_notify_warn(fd, names[i]);
- }
-
- return 0;
-}
-
-static int manager_start_device_monitor(Manager *manager) {
- int r;
-
- assert(manager);
-
- r = manager_init_device_monitor(manager, -EBADF);
- if (r < 0)
- return r;
-
- (void) sd_device_monitor_set_description(manager->monitor, "manager");
-
- r = sd_device_monitor_attach_event(manager->monitor, manager->event);
- if (r < 0)
- return log_error_errno(r, "Failed to attach event to device monitor: %m");
-
- r = sd_device_monitor_start(manager->monitor, on_uevent, manager);
- if (r < 0)
- return log_error_errno(r, "Failed to start device monitor: %m");
-
- r = sd_event_source_set_priority(sd_device_monitor_get_event_source(manager->monitor), EVENT_PRIORITY_DEVICE_MONITOR);
- if (r < 0)
- return log_error_errno(r, "Failed to set priority to device monitor: %m");
-
- return 0;
-}
-
-static int manager_start_worker_notify(Manager *manager) {
- int r;
-
- assert(manager);
- assert(manager->event);
-
- r = notify_socket_prepare(
- manager->event,
- EVENT_PRIORITY_WORKER_NOTIFY,
- on_worker_notify,
- manager,
- &manager->worker_notify_socket_path);
- if (r < 0)
- return log_error_errno(r, "Failed to prepare worker notification socket: %m");
-
- return 0;
-}
-
static int manager_setup_event(Manager *manager) {
_cleanup_(sd_event_unrefp) sd_event *e = NULL;
int r;
return 0;
}
+static int manager_listen_fds(Manager *manager) {
+ _cleanup_strv_free_ char **names = NULL;
+ int r;
+
+ assert(manager);
+
+ int n = sd_listen_fds_with_names(/* unset_environment = */ true, &names);
+ if (n < 0)
+ return n;
+
+ for (int i = 0; i < n; i++) {
+ int fd = SD_LISTEN_FDS_START + i;
+
+ if (streq(names[i], "varlink"))
+ r = 0; /* The fd will be handled by sd_varlink_server_listen_auto(). */
+ else if (streq(names[i], "systemd-udevd-control.socket"))
+ r = manager_init_ctrl(manager, fd);
+ else if (streq(names[i], "systemd-udevd-kernel.socket"))
+ r = manager_init_device_monitor(manager, fd);
+ else if (streq(names[i], "inotify"))
+ r = manager_init_inotify(manager, fd);
+ else
+ r = log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Received unexpected fd (%s), ignoring.", names[i]);
+ if (r < 0)
+ close_and_notify_warn(fd, names[i]);
+ }
+
+ return 0;
+}
+
int manager_main(Manager *manager) {
int r;