sd_event_source *ctrl_event;
sd_event_source *uevent_event;
sd_event_source *inotify_event;
+ sd_event_source *kill_workers_event;
usec_t last_usec;
sd_event_source_unref(manager->ctrl_event);
sd_event_source_unref(manager->uevent_event);
sd_event_source_unref(manager->inotify_event);
+ sd_event_source_unref(manager->kill_workers_event);
sd_event_unref(manager->event);
manager_workers_free(manager);
manager->ctrl_event = sd_event_source_unref(manager->ctrl_event);
manager->uevent_event = sd_event_source_unref(manager->uevent_event);
manager->inotify_event = sd_event_source_unref(manager->inotify_event);
+ manager->kill_workers_event = sd_event_source_unref(manager->kill_workers_event);
manager->event = sd_event_unref(manager->event);
"STATUS=Processing with %u children at max", arg_children_max);
}
+static int on_kill_workers_event(sd_event_source *s, uint64_t usec, void *userdata) {
+ Manager *manager = userdata;
+
+ assert(manager);
+
+ log_debug("Cleanup idle workers");
+ manager_kill_workers(manager);
+
+ return 1;
+}
+
+static int manager_enable_kill_workers_event(Manager *manager) {
+ int enabled, r;
+
+ assert(manager);
+
+ if (!manager->kill_workers_event)
+ goto create_new;
+
+ r = sd_event_source_get_enabled(manager->kill_workers_event, &enabled);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to query whether event source for killing idle workers is enabled or not, trying to create new event source: %m");
+ manager->kill_workers_event = sd_event_source_unref(manager->kill_workers_event);
+ goto create_new;
+ }
+
+ if (enabled == SD_EVENT_ONESHOT)
+ return 0;
+
+ r = sd_event_source_set_time(manager->kill_workers_event, now(CLOCK_MONOTONIC) + 3 * USEC_PER_SEC);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to set time to event source for killing idle workers, trying to create new event source: %m");
+ manager->kill_workers_event = sd_event_source_unref(manager->kill_workers_event);
+ goto create_new;
+ }
+
+ r = sd_event_source_set_enabled(manager->kill_workers_event, SD_EVENT_ONESHOT);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to enable event source for killing idle workers, trying to create new event source: %m");
+ manager->kill_workers_event = sd_event_source_unref(manager->kill_workers_event);
+ goto create_new;
+ }
+
+ return 0;
+
+create_new:
+ r = sd_event_add_time(manager->event, &manager->kill_workers_event, CLOCK_MONOTONIC,
+ now(CLOCK_MONOTONIC) + 3 * USEC_PER_SEC, USEC_PER_SEC, on_kill_workers_event, manager);
+ if (r < 0)
+ return log_warning_errno(r, "Failed to create timer event for killing idle workers: %m");
+
+ return 0;
+}
+
+static int manager_disable_kill_workers_event(Manager *manager) {
+ int r;
+
+ if (!manager->kill_workers_event)
+ return 0;
+
+ r = sd_event_source_set_enabled(manager->kill_workers_event, SD_EVENT_OFF);
+ if (r < 0)
+ return log_warning_errno(r, "Failed to disable event source for cleaning up idle workers, ignoring: %m");
+
+ return 0;
+}
+
static void event_queue_start(Manager *manager) {
struct event *event;
usec_t usec;
manager->last_usec = usec;
}
+ (void) manager_disable_kill_workers_event(manager);
+
udev_builtin_init();
if (!manager->rules) {
assert(manager);
+ (void) manager_disable_kill_workers_event(manager);
+
l = read(fd, &buffer, sizeof(buffer));
if (l < 0) {
if (IN_SET(errno, EAGAIN, EINTR))
/* we can start new workers, try to schedule events */
event_queue_start(manager);
+ /* Disable unnecessary cleanup event */
+ if (hashmap_isempty(manager->workers) && manager->kill_workers_event)
+ (void) sd_event_source_set_enabled(manager->kill_workers_event, SD_EVENT_OFF);
+
return 1;
}
if (!hashmap_isempty(manager->workers)) {
/* There are idle workers */
- log_debug("Cleanup idle workers");
- manager_kill_workers(manager);
+ (void) manager_enable_kill_workers_event(manager);
return 1;
}