From 181a9f65a7cf9059da0f2a44e2152d7636446b33 Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Tue, 21 Apr 2026 08:44:44 +0000 Subject: [PATCH] udev: don't assert on worker cap after killing a broken idle worker manager_can_process_event() considers an event processable if either there is room below children_max to spawn, or an idle worker exists. When only the latter holds, event_run() picks the idle worker and tries device_monitor_send(). If that send fails, event_run() SIGKILLs the worker, marks it WORKER_KILLED and continues the loop. With no other idle worker available, it falls through to worker_spawn(), guarded by: assert(hashmap_size(manager->workers) < manager->config.children_max); The just-killed worker is still in manager->workers until its SIGCHLD is reaped by on_worker_exit(), so at the cap this assertion trips and udevd aborts: Assertion 'hashmap_size(manager->workers) < manager->config.children_max' failed at src/udev/udev-manager.c:635, function event_run(). Aborting. Instead of asserting, bail out when we are already at the worker limit. The event remains in EVENT_QUEUED; once the killed worker's SIGCHLD arrives and frees it from the hashmap, on_post() re-runs event_queue_start() and the event is retried. --- src/udev/udev-manager.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/udev/udev-manager.c b/src/udev/udev-manager.c index 46c8a85d986..7c2530f17fe 100644 --- a/src/udev/udev-manager.c +++ b/src/udev/udev-manager.c @@ -631,8 +631,13 @@ static int event_run(Event *event) { return 0; } + /* No idle worker could accept the event. If we already reached the worker limit, e.g. because + * we just killed the only idle worker above, leave the event queued and wait for SIGCHLD of an + * exiting worker to free up a slot. on_post() will retry processing the queue. */ + if (hashmap_size(manager->workers) >= manager->config.children_max) + return 0; + /* start new worker and pass initial device */ - assert(hashmap_size(manager->workers) < manager->config.children_max); r = worker_spawn(manager, event); if (r < 0) return r; -- 2.47.3