Hashmap *workers;
struct udev_list_node events;
char *cgroup;
+ pid_t pid; /* the process that originally allocated the manager object */
struct udev_rules *rules;
struct udev_list properties;
struct event {
struct udev_list_node node;
+ Manager *manager;
struct udev *udev;
struct udev_device *dev;
struct udev_device *dev_kernel;
};
static void event_free(struct event *event) {
+ int r;
+
if (!event)
return;
if (event->worker)
event->worker->event = NULL;
+ assert(event->manager);
+
+ if (udev_list_node_is_empty(&event->manager->events)) {
+ /* only clean up the queue from the process that created it */
+ if (event->manager->pid == getpid()) {
+ r = unlink("/run/udev/queue");
+ if (r < 0)
+ log_warning_errno(errno, "could not unlink /run/udev/queue: %m");
+ }
+ }
+
free(event);
}
static int event_queue_insert(Manager *manager, struct udev_device *dev) {
struct event *event;
+ int r;
assert(manager);
assert(dev);
+ /* only the main process can add events to the queue */
+ assert(manager->pid == getpid());
+
event = new0(struct event, 1);
- if (event == NULL)
- return -1;
+ if (!event)
+ return -ENOMEM;
event->udev = udev_device_get_udev(dev);
+ event->manager = manager;
event->dev = dev;
event->dev_kernel = udev_device_shallow_clone(dev);
udev_device_copy_properties(event->dev_kernel, dev);
udev_device_get_action(dev), udev_device_get_subsystem(dev));
event->state = EVENT_QUEUED;
+
+ if (udev_list_node_is_empty(&manager->events)) {
+ r = touch("/run/udev/queue");
+ if (r < 0)
+ log_warning_errno(r, "could not touch /run/udev/queue: %m");
+ }
+
udev_list_node_append(&event->node, &manager->events);
+
return 0;
}
return 1;
}
-static void event_queue_update(Manager *manager) {
- int r;
-
- assert(manager);
-
- if (!udev_list_node_is_empty(&manager->events)) {
- r = touch("/run/udev/queue");
- if (r < 0)
- log_warning_errno(r, "could not touch /run/udev/queue: %m");
- } else {
- r = unlink("/run/udev/queue");
- if (r < 0 && errno != ENOENT)
- log_warning("could not unlink /run/udev/queue: %m");
- }
-}
-
/* receive the udevd message from userspace */
static int on_ctrl_msg(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
Manager *manager = userdata;
arg_children_max = i;
}
- if (udev_ctrl_get_ping(ctrl_msg) > 0) {
+ if (udev_ctrl_get_ping(ctrl_msg) > 0)
log_debug("udevd message (SYNC) received");
- /* tell settle that we are busy or idle, this needs to be before the
- * PING handling
- */
- event_queue_update(manager);
- }
if (udev_ctrl_get_exit(ctrl_msg) > 0) {
log_debug("udevd message (EXIT) received");
if (!manager)
return log_oom();
+ manager->pid = getpid();
+
manager->udev = udev_new();
if (!manager->udev)
return log_error_errno(errno, "could not allocate udev context: %m");
timeout = 3 * MSEC_PER_SEC;
}
- /* tell settle that we are busy or idle */
- event_queue_update(manager);
-
fdcount = epoll_wait(fd_ep, ev, ELEMENTSOF(ev), timeout);
if (fdcount < 0)
continue;
exit:
udev_ctrl_cleanup(manager->ctrl);
- unlink("/run/udev/queue");
exit_daemonize:
if (fd_ep >= 0)
close(fd_ep);