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.
This commit is contained in:
committed by
Daan De Meyer
parent
b2d72eabcd
commit
181a9f65a7
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user