Skip to content

Commit 905a89a

Browse files
committed
udev: readjust priorities of event sources
Follow-up for 5116190. Notable changes are - SIGTERM is the highest among others, to make not udevd queue too many events, as we need to serialize them anyway. - device monitor has the second highest priority, to make 'remove' uevents received earlier than IN_IGNORED inotify events. Otherwise, after IN_IGNORED is received, if there is no queued event, /run/udev/queue file will be removed by the post-event source of the inotify event, and 'udevadm settle' or friends may wrongly finish, even we will soon queue 'remove' uevents for the device. This change should fix the recent instability of TEST-64-UDEV-STORAGE. For other changes, see the comments in the code.
1 parent 5de236b commit 905a89a

File tree

4 files changed

+92
-24
lines changed

4 files changed

+92
-24
lines changed

src/udev/udev-manager-ctrl.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ int manager_start_ctrl(Manager *manager) {
125125
/* This needs to be after the inotify and uevent handling, to make sure that the ping is send back
126126
* after fully processing the pending uevents (including the synthetic ones we may create due to
127127
* inotify events). */
128-
r = sd_event_source_set_priority(udev_ctrl_get_event_source(manager->ctrl), SD_EVENT_PRIORITY_IDLE);
128+
r = sd_event_source_set_priority(udev_ctrl_get_event_source(manager->ctrl), EVENT_PRIORITY_CONTROL);
129129
if (r < 0)
130130
return log_error_errno(r, "Failed to set IDLE event priority for udev control event source: %m");
131131

src/udev/udev-manager.c

Lines changed: 68 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ static int manager_reset_kill_workers_timer(Manager *manager) {
219219
USEC_PER_SEC,
220220
on_kill_workers_event,
221221
manager,
222-
SD_EVENT_PRIORITY_NORMAL,
222+
EVENT_PRIORITY_WORKER_TIMER,
223223
"kill-workers-event",
224224
/* force_reset = */ false);
225225
if (r < 0)
@@ -450,13 +450,28 @@ static void worker_attach_event(Worker *worker, Event *event) {
450450
event->state = EVENT_RUNNING;
451451
event->worker = worker;
452452

453-
(void) sd_event_add_time_relative(e, &event->timeout_warning_event, CLOCK_MONOTONIC,
454-
udev_warn_timeout(manager->config.timeout_usec), USEC_PER_SEC,
455-
on_event_timeout_warning, event);
456-
457-
(void) sd_event_add_time_relative(e, &event->timeout_event, CLOCK_MONOTONIC,
458-
manager_kill_worker_timeout(manager), USEC_PER_SEC,
459-
on_event_timeout, event);
453+
(void) event_reset_time_relative(
454+
e,
455+
&event->timeout_warning_event,
456+
CLOCK_MONOTONIC,
457+
udev_warn_timeout(manager->config.timeout_usec),
458+
USEC_PER_SEC,
459+
on_event_timeout_warning,
460+
event,
461+
EVENT_PRIORITY_WORKER_TIMER,
462+
"event-timeout-warn",
463+
/* force_reset = */ true);
464+
465+
(void) event_reset_time_relative(
466+
e,
467+
&event->timeout_event, CLOCK_MONOTONIC,
468+
manager_kill_worker_timeout(manager),
469+
USEC_PER_SEC,
470+
on_event_timeout,
471+
event,
472+
EVENT_PRIORITY_WORKER_TIMER,
473+
"event-timeout-kill",
474+
/* force_reset = */ true);
460475
}
461476

462477
static int worker_spawn(Manager *manager, Event *event) {
@@ -740,10 +755,17 @@ static void event_requeue(Event *event) {
740755
if (event->retry_again_timeout_usec == 0)
741756
event->retry_again_timeout_usec = usec_add(now_usec, EVENT_RETRY_TIMEOUT_USEC);
742757

743-
r = event_reset_time_relative(event->manager->event, &event->retry_event_source,
744-
CLOCK_MONOTONIC, EVENT_RETRY_INTERVAL_USEC, 0,
745-
on_event_retry, NULL,
746-
0, "retry-event", true);
758+
r = event_reset_time_relative(
759+
event->manager->event,
760+
&event->retry_event_source,
761+
CLOCK_MONOTONIC,
762+
EVENT_RETRY_INTERVAL_USEC,
763+
/* accuracy = */ 0,
764+
on_event_retry,
765+
/* userdata = */ NULL,
766+
EVENT_PRIORITY_RETRY_EVENT,
767+
"retry-event",
768+
/* force_reset = */ true);
747769
if (r < 0) {
748770
log_device_warning_errno(
749771
dev, r,
@@ -1216,6 +1238,37 @@ static int on_post(sd_event_source *s, void *userdata) {
12161238
return 0;
12171239
}
12181240

1241+
static int manager_setup_signal(
1242+
Manager *manager,
1243+
sd_event *event,
1244+
int signal,
1245+
sd_event_signal_handler_t handler,
1246+
int64_t priority,
1247+
const char *description) {
1248+
1249+
_cleanup_(sd_event_source_unrefp) sd_event_source *s = NULL;
1250+
int r;
1251+
1252+
assert(manager);
1253+
assert(event);
1254+
1255+
r = sd_event_add_signal(event, &s, signal | SD_EVENT_SIGNAL_PROCMASK, handler, manager);
1256+
if (r < 0)
1257+
return r;
1258+
1259+
r = sd_event_source_set_priority(s, priority);
1260+
if (r < 0)
1261+
return r;
1262+
1263+
(void) sd_event_source_set_description(s, description);
1264+
1265+
r = sd_event_source_set_floating(s, true);
1266+
if (r < 0)
1267+
return r;
1268+
1269+
return 0;
1270+
}
1271+
12191272
static int manager_setup_event(Manager *manager) {
12201273
_cleanup_(sd_event_unrefp) sd_event *e = NULL;
12211274
int r;
@@ -1229,15 +1282,15 @@ static int manager_setup_event(Manager *manager) {
12291282
if (r < 0)
12301283
return log_error_errno(r, "Failed to allocate event loop: %m");
12311284

1232-
r = sd_event_add_signal(e, /* ret_event_source = */ NULL, SIGINT | SD_EVENT_SIGNAL_PROCMASK, on_sigterm, manager);
1285+
r = manager_setup_signal(manager, e, SIGINT, on_sigterm, EVENT_PRIORITY_SIGTERM, "sigint-event-source");
12331286
if (r < 0)
12341287
return log_error_errno(r, "Failed to create SIGINT event source: %m");
12351288

1236-
r = sd_event_add_signal(e, /* ret_event_source = */ NULL, SIGTERM | SD_EVENT_SIGNAL_PROCMASK, on_sigterm, manager);
1289+
r = manager_setup_signal(manager, e, SIGTERM, on_sigterm, EVENT_PRIORITY_SIGTERM, "sigterm-event-source");
12371290
if (r < 0)
12381291
return log_error_errno(r, "Failed to create SIGTERM event source: %m");
12391292

1240-
r = sd_event_add_signal(e, /* ret_event_source = */ NULL, SIGHUP | SD_EVENT_SIGNAL_PROCMASK, on_sighup, manager);
1293+
r = manager_setup_signal(manager, e, SIGHUP, on_sighup, EVENT_PRIORITY_SIGHUP, "sighup-event-source");
12411294
if (r < 0)
12421295
return log_error_errno(r, "Failed to create SIGHUP event source: %m");
12431296

src/udev/udev-manager.h

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,32 @@
1515
#include "udev-ctrl.h"
1616
#include "udev-def.h"
1717

18+
/* This should have a higher priority than the device monitor and inotify watch, to make device monitor and
19+
* inotify event source stopped as soon as possible when the signal is received. Otherwise, we may continue
20+
* receive events that needs to be serialized anyway. */
21+
#define EVENT_PRIORITY_SIGTERM (SD_EVENT_PRIORITY_NORMAL - 6)
22+
/* This must have a higher priority than the inotify event source, to make 'remove' uevent received earlier
23+
* than IN_IGNORED inotify event. */
24+
#define EVENT_PRIORITY_DEVICE_MONITOR (SD_EVENT_PRIORITY_NORMAL - 5)
1825
/* This must have a higher priority than the worker notification, to make IN_IGNORED event received earlier
1926
* than notifications about requests of adding/removing inotify watches. */
20-
#define EVENT_PRIORITY_INOTIFY_WATCH (SD_EVENT_PRIORITY_NORMAL - 30)
27+
#define EVENT_PRIORITY_INOTIFY_WATCH (SD_EVENT_PRIORITY_NORMAL - 4)
2128
/* This must have a higher priority than the worker SIGCHLD event, to make notifications about completions of
2229
* processing events received before SIGCHLD. */
23-
#define EVENT_PRIORITY_WORKER_NOTIFY (SD_EVENT_PRIORITY_NORMAL - 20)
24-
/* This should have a higher priority than other events, especially timer events about killing long running
25-
* worker processes or idle worker processes. */
26-
#define EVENT_PRIORITY_WORKER_SIGCHLD (SD_EVENT_PRIORITY_NORMAL - 10)
27-
/* This should have a lower priority to make signal and timer event sources processed earlier. */
28-
#define EVENT_PRIORITY_DEVICE_MONITOR (SD_EVENT_PRIORITY_NORMAL + 10)
30+
#define EVENT_PRIORITY_WORKER_NOTIFY (SD_EVENT_PRIORITY_NORMAL - 3)
31+
/* This should have a higher priority than timer events about killing long running worker processes or idle
32+
* worker processes. */
33+
#define EVENT_PRIORITY_WORKER_SIGCHLD (SD_EVENT_PRIORITY_NORMAL - 2)
34+
/* As said in the above, this should have a lower proority than the SIGCHLD event source. */
35+
#define EVENT_PRIORITY_WORKER_TIMER (SD_EVENT_PRIORITY_NORMAL - 1)
36+
/* This should have a lower priority than most event sources, but let's process earlier than varlink and the
37+
* legacy control socket. */
38+
#define EVENT_PRIORITY_SIGHUP (SD_EVENT_PRIORITY_NORMAL + 1)
39+
/* Let's not interrupt the service by any user process, even that requires privileges. */
40+
#define EVENT_PRIORITY_VARLINK (SD_EVENT_PRIORITY_NORMAL + 2)
41+
#define EVENT_PRIORITY_CONTROL (SD_EVENT_PRIORITY_NORMAL + 2)
42+
/* The event is intended to trigger the post-event source, hence can be the lowest priority. */
43+
#define EVENT_PRIORITY_RETRY_EVENT (SD_EVENT_PRIORITY_NORMAL + 3)
2944

3045
typedef struct Event Event;
3146
typedef struct UdevRules UdevRules;

src/udev/udev-varlink.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ int manager_start_varlink_server(Manager *manager) {
170170
/* This needs to be after the inotify and uevent handling, to make sure that the ping is send back
171171
* after fully processing the pending uevents (including the synthetic ones we may create due to
172172
* inotify events). */
173-
r = sd_varlink_server_attach_event(v, manager->event, SD_EVENT_PRIORITY_IDLE);
173+
r = sd_varlink_server_attach_event(v, manager->event, EVENT_PRIORITY_VARLINK);
174174
if (r < 0)
175175
return log_error_errno(r, "Failed to attach Varlink connection to event loop: %m");
176176

0 commit comments

Comments
 (0)