diff --git a/src/udev/udev-manager.c b/src/udev/udev-manager.c index d218b8bef7..452a68778e 100644 --- a/src/udev/udev-manager.c +++ b/src/udev/udev-manager.c @@ -1312,13 +1312,17 @@ static int on_post(sd_event_source *s, void *userdata) { if (sd_event_source_get_pending(sd_device_monitor_get_event_source(manager->monitor)) != 0) return 0; + /* We are currently synthesizing change uevents, hence new uevents may come soon. */ + if (!set_isempty(manager->synthesize_change_child_event_sources)) + return 0; + (void) manager_unlink_queue_file(manager); (void) manager_reset_kill_workers_timer(manager); if (!hashmap_isempty(manager->workers)) return 0; /* There still exist idle workers. */ - if (manager->workers_cgroup && set_isempty(manager->synthesize_change_child_event_sources)) + if (manager->workers_cgroup) /* cleanup possible left-over processes in the workers cgroup */ if (cg_kill_kernel_sigkill(manager->workers_cgroup, /* ret_n_pids_killed= */ NULL) == -EOPNOTSUPP) (void) cg_kill(manager->workers_cgroup, SIGKILL, CGROUP_IGNORE_SELF, /* killed_pids= */ NULL, /* log_kill= */ NULL, /* userdata= */ NULL); @@ -1379,10 +1383,21 @@ static int manager_setup_event(Manager *manager) { if (r < 0) return log_error_errno(r, "Failed to create SIGHUP event source: %m"); - r = sd_event_add_post(e, /* ret= */ NULL, on_post, manager); + _cleanup_(sd_event_source_unrefp) sd_event_source *s = NULL; + r = sd_event_add_post(e, &s, on_post, manager); if (r < 0) return log_error_errno(r, "Failed to create post event source: %m"); + r = sd_event_source_set_priority(s, EVENT_PRIORITY_POST); + if (r < 0) + return log_error_errno(r, "Failed to set priority to post event source: %m"); + + (void) sd_event_source_set_description(s, "post-event-source"); + + r = sd_event_source_set_floating(s, true); + if (r < 0) + return log_error_errno(r, "Failed to set floating to post event source: %m"); + /* Eventually, we probably want to do more here on memory pressure, for example, kill idle workers immediately */ r = sd_event_add_memory_pressure(e, /* ret= */ NULL, /* callback= */ NULL, /* userdata= */ NULL); if (r < 0) diff --git a/src/udev/udev-manager.h b/src/udev/udev-manager.h index 9ff81acd9f..48ac3cc067 100644 --- a/src/udev/udev-manager.h +++ b/src/udev/udev-manager.h @@ -13,20 +13,23 @@ /* This should have a higher priority than the device monitor and inotify watch, to make device monitor and * inotify event source stopped as soon as possible when the signal is received. Otherwise, we may continue * receive events that needs to be serialized anyway. */ -#define EVENT_PRIORITY_SIGTERM (SD_EVENT_PRIORITY_NORMAL - 6) +#define EVENT_PRIORITY_SIGTERM (SD_EVENT_PRIORITY_NORMAL - 7) /* This must have a higher priority than the worker notification, to make IN_IGNORED event received earlier * than notifications about requests of adding/removing inotify watches. */ -#define EVENT_PRIORITY_INOTIFY_WATCH (SD_EVENT_PRIORITY_NORMAL - 5) +#define EVENT_PRIORITY_INOTIFY_WATCH (SD_EVENT_PRIORITY_NORMAL - 6) /* This must have a higher priority than the worker exit event, to make notifications about completions of * processing events received before exit. */ -#define EVENT_PRIORITY_WORKER_NOTIFY (SD_EVENT_PRIORITY_NORMAL - 4) +#define EVENT_PRIORITY_WORKER_NOTIFY (SD_EVENT_PRIORITY_NORMAL - 5) /* This should have a higher priority than timer events about killing long running worker processes or idle * worker processes. */ -#define EVENT_PRIORITY_WORKER_EXIT (SD_EVENT_PRIORITY_NORMAL - 3) +#define EVENT_PRIORITY_WORKER_EXIT (SD_EVENT_PRIORITY_NORMAL - 4) /* As mentioned above, this should have a lower priority than the exit event source. */ -#define EVENT_PRIORITY_WORKER_TIMER (SD_EVENT_PRIORITY_NORMAL - 2) -/* This must have a lower priority than the worker event source. Otherwise, flood of uevents delays worker - * sigchld events or notifications, and workers will not continue to process events. */ +#define EVENT_PRIORITY_WORKER_TIMER (SD_EVENT_PRIORITY_NORMAL - 3) +/* This must have a higher priority than the device monitor to prevent uevent floods from starving + * event_queue_start(), but lower than worker event sources to observe worker completions first. */ +#define EVENT_PRIORITY_POST (SD_EVENT_PRIORITY_NORMAL - 2) +/* This must have a lower priority than the worker event source and post event source. Otherwise, flood of + * uevents delays worker sigchld events or notifications, and workers will not continue to process events. */ #define EVENT_PRIORITY_DEVICE_MONITOR (SD_EVENT_PRIORITY_NORMAL - 1) /* This should have a lower priority than most event sources, but let's process earlier than varlink and the * legacy control socket. */