1
0
mirror of https://github.com/systemd/systemd.git synced 2025-01-11 09:18:07 +03:00

manager: split out helper that gets Unit objects with interest in given PidRef

This is both easier to read and allows us to reuse the helper later.
This commit is contained in:
Lennart Poettering 2024-04-23 18:32:16 +02:00
parent c2e6ed612a
commit 4414bd5932

View File

@ -2613,6 +2613,59 @@ static void manager_invoke_notify_message(
}
}
static int manager_get_units_for_pidref(Manager *m, const PidRef *pidref, Unit ***ret_units) {
/* Determine array of every unit that is interested in the specified process */
assert(m);
assert(pidref_is_set(pidref));
Unit *u1, *u2, **array;
u1 = manager_get_unit_by_pidref_cgroup(m, pidref);
u2 = hashmap_get(m->watch_pids, pidref);
array = hashmap_get(m->watch_pids_more, pidref);
size_t n = 0;
if (u1)
n++;
if (u2)
n++;
if (array)
for (size_t j = 0; array[j]; j++)
n++;
assert(n <= INT_MAX); /* Make sure we can reasonably return the counter as "int" */
if (ret_units) {
_cleanup_free_ Unit **units = NULL;
if (n > 0) {
units = new(Unit*, n + 1);
if (!units)
return -ENOMEM;
/* We return a dense array, and put the "main" unit first, i.e. unit in whose cgroup
* the process currently is. Note that we do not bother with filtering duplicates
* here. */
size_t i = 0;
if (u1)
units[i++] = u1;
if (u2)
units[i++] = u2;
if (array)
for (size_t j = 0; array[j]; j++)
units[i++] = array[j];
assert(i == n);
units[i] = NULL; /* end array in an extra NULL */
}
*ret_units = TAKE_PTR(units);
}
return (int) n;
}
static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
Manager *m = ASSERT_PTR(userdata);
_cleanup_fdset_free_ FDSet *fds = NULL;
@ -2632,12 +2685,9 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t
struct cmsghdr *cmsg;
struct ucred *ucred = NULL;
_cleanup_free_ Unit **array_copy = NULL;
_cleanup_strv_free_ char **tags = NULL;
Unit *u1, *u2, **array;
int r, *fd_array = NULL;
size_t n_fds = 0;
bool found = false;
ssize_t n;
assert(m->notify_fd == fd);
@ -2725,37 +2775,20 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t
PidRef pidref = PIDREF_MAKE_FROM_PID(ucred->pid);
/* Notify every unit that might be interested, which might be multiple. */
u1 = manager_get_unit_by_pidref_cgroup(m, &pidref);
u2 = hashmap_get(m->watch_pids, &pidref);
array = hashmap_get(m->watch_pids_more, &pidref);
if (array) {
size_t k = 0;
_cleanup_free_ Unit **array = NULL;
while (array[k])
k++;
array_copy = newdup(Unit*, array, k+1);
if (!array_copy)
log_oom();
int n_array = manager_get_units_for_pidref(m, &pidref, &array);
if (n_array < 0) {
log_warning_errno(n_array, "Failed to determine units for PID " PID_FMT ", ignoring: %m", ucred->pid);
return 0;
}
/* And now invoke the per-unit callbacks. Note that manager_invoke_notify_message() will handle
* duplicate units make sure we only invoke each unit's handler once. */
if (u1) {
manager_invoke_notify_message(m, u1, ucred, tags, fds);
found = true;
}
if (u2) {
manager_invoke_notify_message(m, u2, ucred, tags, fds);
found = true;
}
if (array_copy)
for (size_t i = 0; array_copy[i]; i++) {
manager_invoke_notify_message(m, array_copy[i], ucred, tags, fds);
found = true;
}
if (!found)
log_warning("Cannot find unit for notify message of PID "PID_FMT", ignoring.", ucred->pid);
if (n_array == 0)
log_debug("Cannot find unit for notify message of PID "PID_FMT", ignoring.", ucred->pid);
else
/* And now invoke the per-unit callbacks. Note that manager_invoke_notify_message() will handle
* duplicate units making sure we only invoke each unit's handler once. */
FOREACH_ARRAY(u, array, n_array)
manager_invoke_notify_message(m, *u, ucred, tags, fds);
if (!fdset_isempty(fds))
log_warning("Got extra auxiliary fds with notification message, closing them.");