mirror of
https://github.com/systemd/systemd.git
synced 2025-01-26 14:04:03 +03:00
udevd: wait 3 seconds before killing worker processes
During boot process, many worker processes are forked and killed. To decrease cycles of forking and killing worker, let's wait 3 seconds before killing workers. If new uevent or inotify event comes within the delay, the killing porcess will be cancelled.
This commit is contained in:
parent
da14313418
commit
eca195ec23
@ -86,6 +86,7 @@ typedef struct Manager {
|
||||
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;
|
||||
|
||||
@ -284,6 +285,7 @@ static void manager_free(Manager *manager) {
|
||||
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);
|
||||
@ -364,6 +366,7 @@ static void worker_spawn(Manager *manager, struct event *event) {
|
||||
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);
|
||||
|
||||
@ -767,6 +770,73 @@ static void manager_reload(Manager *manager) {
|
||||
"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;
|
||||
@ -788,6 +858,8 @@ static void event_queue_start(Manager *manager) {
|
||||
manager->last_usec = usec;
|
||||
}
|
||||
|
||||
(void) manager_disable_kill_workers_event(manager);
|
||||
|
||||
udev_builtin_init();
|
||||
|
||||
if (!manager->rules) {
|
||||
@ -1159,6 +1231,8 @@ static int on_inotify(sd_event_source *s, int fd, uint32_t revents, void *userda
|
||||
|
||||
assert(manager);
|
||||
|
||||
(void) manager_disable_kill_workers_event(manager);
|
||||
|
||||
l = read(fd, &buffer, sizeof(buffer));
|
||||
if (l < 0) {
|
||||
if (IN_SET(errno, EAGAIN, EINTR))
|
||||
@ -1258,6 +1332,10 @@ static int on_sigchld(sd_event_source *s, const struct signalfd_siginfo *si, voi
|
||||
/* 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;
|
||||
}
|
||||
|
||||
@ -1273,8 +1351,7 @@ static int on_post(sd_event_source *s, void *userdata) {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user