Merge pull request #29594 from poettering/cgroup-rename-ret-params

more pidfdification
This commit is contained in:
Lennart Poettering
2023-10-18 17:25:44 +02:00
committed by GitHub
49 changed files with 708 additions and 422 deletions
+76 -72
View File
@@ -291,7 +291,6 @@ static int cg_kill_items(
_cleanup_set_free_ Set *allocated_set = NULL;
bool done = false;
int r, ret = 0, ret_log_kill = 0;
pid_t my_pid;
assert(sig >= 0);
@@ -310,11 +309,8 @@ static int cg_kill_items(
return -ENOMEM;
}
my_pid = getpid_cached();
do {
_cleanup_fclose_ FILE *f = NULL;
pid_t pid = 0;
done = true;
r = cg_enumerate_items(SYSTEMD_CGROUP_CONTROLLER, path, &f, item);
@@ -325,25 +321,32 @@ static int cg_kill_items(
return ret;
}
while ((r = cg_read_pid(f, &pid)) > 0) {
for (;;) {
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
if ((flags & CGROUP_IGNORE_SELF) && pid == my_pid)
r = cg_read_pidref(f, &pidref);
if (r < 0)
return r;
if (r == 0)
break;
if ((flags & CGROUP_IGNORE_SELF) && pidref_is_self(&pidref))
continue;
if (set_get(s, PID_TO_PTR(pid)) == PID_TO_PTR(pid))
if (set_get(s, PID_TO_PTR(pidref.pid)) == PID_TO_PTR(pidref.pid))
continue;
if (log_kill)
ret_log_kill = log_kill(pid, sig, userdata);
ret_log_kill = log_kill(&pidref, sig, userdata);
/* If we haven't killed this process yet, kill
* it */
if (kill(pid, sig) < 0) {
if (ret >= 0 && errno != ESRCH)
ret = -errno;
/* If we haven't killed this process yet, kill it */
r = pidref_kill(&pidref, sig);
if (r < 0) {
if (ret >= 0 && r != -ESRCH)
ret = r;
} else {
if (flags & CGROUP_SIGCONT)
(void) kill(pid, SIGCONT);
(void) pidref_kill(&pidref, SIGCONT);
if (ret == 0) {
if (log_kill)
@@ -355,7 +358,7 @@ static int cg_kill_items(
done = false;
r = set_put(s, PID_TO_PTR(pid));
r = set_put(s, PID_TO_PTR(pidref.pid));
if (r < 0) {
if (ret >= 0)
return r;
@@ -622,11 +625,11 @@ static int controller_is_v1_accessible(const char *root, const char *controller)
return laccess(cpath, root ? W_OK : F_OK);
}
int cg_get_path_and_check(const char *controller, const char *path, const char *suffix, char **fs) {
int cg_get_path_and_check(const char *controller, const char *path, const char *suffix, char **ret) {
int r;
assert(controller);
assert(fs);
assert(ret);
if (!cg_controller_is_valid(controller))
return -EINVAL;
@@ -646,7 +649,7 @@ int cg_get_path_and_check(const char *controller, const char *path, const char *
return r;
}
return cg_get_path(controller, path, suffix, fs);
return cg_get_path(controller, path, suffix, ret);
}
int cg_set_xattr(const char *path, const char *name, const void *value, size_t size, int flags) {
@@ -809,7 +812,7 @@ int cg_pid_get_path(const char *controller, pid_t pid, char **ret_path) {
}
}
int cg_pidref_get_path(const char *controller, PidRef *pidref, char **ret_path) {
int cg_pidref_get_path(const char *controller, const PidRef *pidref, char **ret_path) {
_cleanup_free_ char *path = NULL;
int r;
@@ -1052,30 +1055,30 @@ int cg_split_spec(const char *spec, char **ret_controller, char **ret_path) {
return 0;
}
int cg_mangle_path(const char *path, char **result) {
int cg_mangle_path(const char *path, char **ret) {
_cleanup_free_ char *c = NULL, *p = NULL;
int r;
assert(path);
assert(result);
assert(ret);
/* First, check if it already is a filesystem path */
if (path_startswith(path, "/sys/fs/cgroup"))
return path_simplify_alloc(path, result);
return path_simplify_alloc(path, ret);
/* Otherwise, treat it as cg spec */
r = cg_split_spec(path, &c, &p);
if (r < 0)
return r;
return cg_get_path(c ?: SYSTEMD_CGROUP_CONTROLLER, p ?: "/", NULL, result);
return cg_get_path(c ?: SYSTEMD_CGROUP_CONTROLLER, p ?: "/", NULL, ret);
}
int cg_get_root_path(char **path) {
int cg_get_root_path(char **ret_path) {
char *p, *e;
int r;
assert(path);
assert(ret_path);
r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 1, &p);
if (r < 0)
@@ -1089,17 +1092,17 @@ int cg_get_root_path(char **path) {
if (e)
*e = 0;
*path = p;
*ret_path = p;
return 0;
}
int cg_shift_path(const char *cgroup, const char *root, const char **shifted) {
int cg_shift_path(const char *cgroup, const char *root, const char **ret_shifted) {
_cleanup_free_ char *rt = NULL;
char *p;
int r;
assert(cgroup);
assert(shifted);
assert(ret_shifted);
if (!root) {
/* If the root was specified let's use that, otherwise
@@ -1114,20 +1117,20 @@ int cg_shift_path(const char *cgroup, const char *root, const char **shifted) {
p = path_startswith(cgroup, root);
if (p && p > cgroup)
*shifted = p - 1;
*ret_shifted = p - 1;
else
*shifted = cgroup;
*ret_shifted = cgroup;
return 0;
}
int cg_pid_get_path_shifted(pid_t pid, const char *root, char **cgroup) {
int cg_pid_get_path_shifted(pid_t pid, const char *root, char **ret_cgroup) {
_cleanup_free_ char *raw = NULL;
const char *c;
int r;
assert(pid >= 0);
assert(cgroup);
assert(ret_cgroup);
r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &raw);
if (r < 0)
@@ -1138,7 +1141,7 @@ int cg_pid_get_path_shifted(pid_t pid, const char *root, char **cgroup) {
return r;
if (c == raw)
*cgroup = TAKE_PTR(raw);
*ret_cgroup = TAKE_PTR(raw);
else {
char *n;
@@ -1146,18 +1149,18 @@ int cg_pid_get_path_shifted(pid_t pid, const char *root, char **cgroup) {
if (!n)
return -ENOMEM;
*cgroup = n;
*ret_cgroup = n;
}
return 0;
}
int cg_path_decode_unit(const char *cgroup, char **unit) {
int cg_path_decode_unit(const char *cgroup, char **ret_unit) {
char *c, *s;
size_t n;
assert(cgroup);
assert(unit);
assert(ret_unit);
n = strcspn(cgroup, "/");
if (n < 3)
@@ -1173,7 +1176,7 @@ int cg_path_decode_unit(const char *cgroup, char **unit) {
if (!s)
return -ENOMEM;
*unit = s;
*ret_unit = s;
return 0;
}
@@ -1261,17 +1264,17 @@ int cg_path_get_unit_path(const char *path, char **ret) {
return 0;
}
int cg_pid_get_unit(pid_t pid, char **unit) {
int cg_pid_get_unit(pid_t pid, char **ret_unit) {
_cleanup_free_ char *cgroup = NULL;
int r;
assert(unit);
assert(ret_unit);
r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
if (r < 0)
return r;
return cg_path_get_unit(cgroup, unit);
return cg_path_get_unit(cgroup, ret_unit);
}
/**
@@ -1381,20 +1384,20 @@ int cg_path_get_user_unit(const char *path, char **ret) {
return cg_path_get_unit(t, ret);
}
int cg_pid_get_user_unit(pid_t pid, char **unit) {
int cg_pid_get_user_unit(pid_t pid, char **ret_unit) {
_cleanup_free_ char *cgroup = NULL;
int r;
assert(unit);
assert(ret_unit);
r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
if (r < 0)
return r;
return cg_path_get_user_unit(cgroup, unit);
return cg_path_get_user_unit(cgroup, ret_unit);
}
int cg_path_get_machine_name(const char *path, char **machine) {
int cg_path_get_machine_name(const char *path, char **ret_machine) {
_cleanup_free_ char *u = NULL;
const char *sl;
int r;
@@ -1404,20 +1407,20 @@ int cg_path_get_machine_name(const char *path, char **machine) {
return r;
sl = strjoina("/run/systemd/machines/unit:", u);
return readlink_malloc(sl, machine);
return readlink_malloc(sl, ret_machine);
}
int cg_pid_get_machine_name(pid_t pid, char **machine) {
int cg_pid_get_machine_name(pid_t pid, char **ret_machine) {
_cleanup_free_ char *cgroup = NULL;
int r;
assert(machine);
assert(ret_machine);
r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
if (r < 0)
return r;
return cg_path_get_machine_name(cgroup, machine);
return cg_path_get_machine_name(cgroup, ret_machine);
}
int cg_path_get_cgroupid(const char *path, uint64_t *ret) {
@@ -1436,7 +1439,7 @@ int cg_path_get_cgroupid(const char *path, uint64_t *ret) {
return 0;
}
int cg_path_get_session(const char *path, char **session) {
int cg_path_get_session(const char *path, char **ret_session) {
_cleanup_free_ char *unit = NULL;
char *start, *end;
int r;
@@ -1458,20 +1461,20 @@ int cg_path_get_session(const char *path, char **session) {
if (!session_id_valid(start))
return -ENXIO;
if (session) {
if (ret_session) {
char *rr;
rr = strdup(start);
if (!rr)
return -ENOMEM;
*session = rr;
*ret_session = rr;
}
return 0;
}
int cg_pid_get_session(pid_t pid, char **session) {
int cg_pid_get_session(pid_t pid, char **ret_session) {
_cleanup_free_ char *cgroup = NULL;
int r;
@@ -1479,10 +1482,10 @@ int cg_pid_get_session(pid_t pid, char **session) {
if (r < 0)
return r;
return cg_path_get_session(cgroup, session);
return cg_path_get_session(cgroup, ret_session);
}
int cg_path_get_owner_uid(const char *path, uid_t *uid) {
int cg_path_get_owner_uid(const char *path, uid_t *ret_uid) {
_cleanup_free_ char *slice = NULL;
char *start, *end;
int r;
@@ -1496,18 +1499,19 @@ int cg_path_get_owner_uid(const char *path, uid_t *uid) {
start = startswith(slice, "user-");
if (!start)
return -ENXIO;
end = endswith(start, ".slice");
if (!end)
return -ENXIO;
*end = 0;
if (parse_uid(start, uid) < 0)
if (parse_uid(start, ret_uid) < 0)
return -ENXIO;
return 0;
}
int cg_pid_get_owner_uid(pid_t pid, uid_t *uid) {
int cg_pid_get_owner_uid(pid_t pid, uid_t *ret_uid) {
_cleanup_free_ char *cgroup = NULL;
int r;
@@ -1515,14 +1519,14 @@ int cg_pid_get_owner_uid(pid_t pid, uid_t *uid) {
if (r < 0)
return r;
return cg_path_get_owner_uid(cgroup, uid);
return cg_path_get_owner_uid(cgroup, ret_uid);
}
int cg_path_get_slice(const char *p, char **slice) {
int cg_path_get_slice(const char *p, char **ret_slice) {
const char *e = NULL;
assert(p);
assert(slice);
assert(ret_slice);
/* Finds the right-most slice unit from the beginning, but
* stops before we come to the first non-slice unit. */
@@ -1542,11 +1546,11 @@ int cg_path_get_slice(const char *p, char **slice) {
if (!s)
return -ENOMEM;
*slice = s;
*ret_slice = s;
return 0;
}
return cg_path_decode_unit(e, slice);
return cg_path_decode_unit(e, ret_slice);
}
e = p;
@@ -1554,44 +1558,44 @@ int cg_path_get_slice(const char *p, char **slice) {
}
}
int cg_pid_get_slice(pid_t pid, char **slice) {
int cg_pid_get_slice(pid_t pid, char **ret_slice) {
_cleanup_free_ char *cgroup = NULL;
int r;
assert(slice);
assert(ret_slice);
r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
if (r < 0)
return r;
return cg_path_get_slice(cgroup, slice);
return cg_path_get_slice(cgroup, ret_slice);
}
int cg_path_get_user_slice(const char *p, char **slice) {
int cg_path_get_user_slice(const char *p, char **ret_slice) {
const char *t;
assert(p);
assert(slice);
assert(ret_slice);
t = skip_user_prefix(p);
if (!t)
return -ENXIO;
/* And now it looks pretty much the same as for a system
* slice, so let's just use the same parser from here on. */
return cg_path_get_slice(t, slice);
/* And now it looks pretty much the same as for a system slice, so let's just use the same parser
* from here on. */
return cg_path_get_slice(t, ret_slice);
}
int cg_pid_get_user_slice(pid_t pid, char **slice) {
int cg_pid_get_user_slice(pid_t pid, char **ret_slice) {
_cleanup_free_ char *cgroup = NULL;
int r;
assert(slice);
assert(ret_slice);
r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
if (r < 0)
return r;
return cg_path_get_user_slice(cgroup, slice);
return cg_path_get_user_slice(cgroup, ret_slice);
}
bool cg_needs_escape(const char *p) {
+24 -24
View File
@@ -191,20 +191,20 @@ typedef enum CGroupFlags {
CGROUP_REMOVE = 1 << 2,
} CGroupFlags;
typedef int (*cg_kill_log_func_t)(pid_t pid, int sig, void *userdata);
typedef int (*cg_kill_log_func_t)(const PidRef *pid, int sig, void *userdata);
int cg_kill(const char *path, int sig, CGroupFlags flags, Set *s, cg_kill_log_func_t kill_log, void *userdata);
int cg_kill_kernel_sigkill(const char *path);
int cg_kill_recursive(const char *path, int sig, CGroupFlags flags, Set *s, cg_kill_log_func_t kill_log, void *userdata);
int cg_split_spec(const char *spec, char **ret_controller, char **ret_path);
int cg_mangle_path(const char *path, char **result);
int cg_mangle_path(const char *path, char **ret);
int cg_get_path(const char *controller, const char *path, const char *suffix, char **fs);
int cg_get_path_and_check(const char *controller, const char *path, const char *suffix, char **fs);
int cg_get_path(const char *controller, const char *path, const char *suffix, char **ret);
int cg_get_path_and_check(const char *controller, const char *path, const char *suffix, char **ret);
int cg_pid_get_path(const char *controller, pid_t pid, char **path);
int cg_pidref_get_path(const char *controller, PidRef *pidref, char **path);
int cg_pid_get_path(const char *controller, pid_t pid, char **ret);
int cg_pidref_get_path(const char *controller, const PidRef *pidref, char **ret);
int cg_rmdir(const char *controller, const char *path);
@@ -263,27 +263,27 @@ int cg_is_empty_recursive(const char *controller, const char *path);
int cg_get_root_path(char **path);
int cg_path_get_cgroupid(const char *path, uint64_t *ret);
int cg_path_get_session(const char *path, char **session);
int cg_path_get_owner_uid(const char *path, uid_t *uid);
int cg_path_get_unit(const char *path, char **unit);
int cg_path_get_unit_path(const char *path, char **unit);
int cg_path_get_user_unit(const char *path, char **unit);
int cg_path_get_machine_name(const char *path, char **machine);
int cg_path_get_slice(const char *path, char **slice);
int cg_path_get_user_slice(const char *path, char **slice);
int cg_path_get_session(const char *path, char **ret_session);
int cg_path_get_owner_uid(const char *path, uid_t *ret_uid);
int cg_path_get_unit(const char *path, char **ret_unit);
int cg_path_get_unit_path(const char *path, char **ret_unit);
int cg_path_get_user_unit(const char *path, char **ret_unit);
int cg_path_get_machine_name(const char *path, char **ret_machine);
int cg_path_get_slice(const char *path, char **ret_slice);
int cg_path_get_user_slice(const char *path, char **ret_slice);
int cg_shift_path(const char *cgroup, const char *cached_root, const char **shifted);
int cg_pid_get_path_shifted(pid_t pid, const char *cached_root, char **cgroup);
int cg_shift_path(const char *cgroup, const char *cached_root, const char **ret_shifted);
int cg_pid_get_path_shifted(pid_t pid, const char *cached_root, char **ret_cgroup);
int cg_pid_get_session(pid_t pid, char **session);
int cg_pid_get_owner_uid(pid_t pid, uid_t *uid);
int cg_pid_get_unit(pid_t pid, char **unit);
int cg_pid_get_user_unit(pid_t pid, char **unit);
int cg_pid_get_machine_name(pid_t pid, char **machine);
int cg_pid_get_slice(pid_t pid, char **slice);
int cg_pid_get_user_slice(pid_t pid, char **slice);
int cg_pid_get_session(pid_t pid, char **ret_session);
int cg_pid_get_owner_uid(pid_t pid, uid_t *ret_uid);
int cg_pid_get_unit(pid_t pid, char **ret_unit);
int cg_pid_get_user_unit(pid_t pid, char **ret_unit);
int cg_pid_get_machine_name(pid_t pid, char **ret_machine);
int cg_pid_get_slice(pid_t pid, char **ret_slice);
int cg_pid_get_user_slice(pid_t pid, char **ret_slice);
int cg_path_decode_unit(const char *cgroup, char **unit);
int cg_path_decode_unit(const char *cgroup, char **ret_unit);
bool cg_needs_escape(const char *p);
int cg_escape(const char *p, char **ret);
+1 -1
View File
@@ -1451,7 +1451,7 @@ void log_received_signal(int level, const struct signalfd_siginfo *si) {
if (pid_is_valid(si->ssi_pid)) {
_cleanup_free_ char *p = NULL;
(void) get_process_comm(si->ssi_pid, &p);
(void) pid_get_comm(si->ssi_pid, &p);
log_full(level,
"Received SIG%s from PID %"PRIu32" (%s).",
+14 -4
View File
@@ -186,7 +186,7 @@ int pidref_new_from_pid(pid_t pid, PidRef **ret) {
return 0;
}
int pidref_kill(PidRef *pidref, int sig) {
int pidref_kill(const PidRef *pidref, int sig) {
if (!pidref)
return -ESRCH;
@@ -200,7 +200,7 @@ int pidref_kill(PidRef *pidref, int sig) {
return -ESRCH;
}
int pidref_kill_and_sigcont(PidRef *pidref, int sig) {
int pidref_kill_and_sigcont(const PidRef *pidref, int sig) {
int r;
r = pidref_kill(pidref, sig);
@@ -213,7 +213,7 @@ int pidref_kill_and_sigcont(PidRef *pidref, int sig) {
return 0;
}
int pidref_sigqueue(PidRef *pidref, int sig, int value) {
int pidref_sigqueue(const PidRef *pidref, int sig, int value) {
if (!pidref)
return -ESRCH;
@@ -240,7 +240,7 @@ int pidref_sigqueue(PidRef *pidref, int sig, int value) {
return -ESRCH;
}
int pidref_verify(PidRef *pidref) {
int pidref_verify(const PidRef *pidref) {
int r;
/* This is a helper that is supposed to be called after reading information from procfs via a
@@ -250,6 +250,9 @@ int pidref_verify(PidRef *pidref) {
if (!pidref_is_set(pidref))
return -ESRCH;
if (pidref->pid == 1)
return 1; /* PID 1 can never go away, hence never be recycled to a different process → return 1 */
if (pidref->fd < 0)
return 0; /* If we don't have a pidfd we cannot validate it, hence we assume it's all OK → return 0 */
@@ -260,6 +263,13 @@ int pidref_verify(PidRef *pidref) {
return 1; /* We have a pidfd and it still points to the PID we have, hence all is *really* OK → return 1 */
}
bool pidref_is_self(const PidRef *pidref) {
if (!pidref)
return false;
return pidref->pid == getpid_cached();
}
static void pidref_hash_func(const PidRef *pidref, struct siphash *state) {
siphash24_compress(&pidref->pid, sizeof(pidref->pid), state);
}
+6 -4
View File
@@ -43,6 +43,8 @@ static inline int pidref_set_self(PidRef *pidref) {
return pidref_set_pid(pidref, 0);
}
bool pidref_is_self(const PidRef *pidref);
void pidref_done(PidRef *pidref);
PidRef *pidref_free(PidRef *pidref);
DEFINE_TRIVIAL_CLEANUP_FUNC(PidRef*, pidref_free);
@@ -51,11 +53,11 @@ int pidref_dup(const PidRef *pidref, PidRef **ret);
int pidref_new_from_pid(pid_t pid, PidRef **ret);
int pidref_kill(PidRef *pidref, int sig);
int pidref_kill_and_sigcont(PidRef *pidref, int sig);
int pidref_sigqueue(PidRef *pidfref, int sig, int value);
int pidref_kill(const PidRef *pidref, int sig);
int pidref_kill_and_sigcont(const PidRef *pidref, int sig);
int pidref_sigqueue(const PidRef *pidfref, int sig, int value);
int pidref_verify(PidRef *pidref);
int pidref_verify(const PidRef *pidref);
#define TAKE_PIDREF(p) TAKE_GENERIC((p), PidRef, PIDREF_NULL)
+2 -2
View File
@@ -128,7 +128,7 @@ int proc_cmdline(char **ret) {
}
if (detect_container() > 0)
return get_process_cmdline(1, SIZE_MAX, 0, ret);
return pid_get_cmdline(1, SIZE_MAX, 0, ret);
else
return read_full_file("/proc/cmdline", ret, NULL);
}
@@ -147,7 +147,7 @@ static int proc_cmdline_strv_internal(char ***ret, bool filter_pid1_args) {
if (detect_container() > 0) {
_cleanup_strv_free_ char **args = NULL;
r = get_process_cmdline_strv(1, /* flags = */ 0, &args);
r = pid_get_cmdline_strv(1, /* flags = */ 0, &args);
if (r < 0)
return r;
+250 -21
View File
@@ -25,6 +25,7 @@
#include "alloc-util.h"
#include "architecture.h"
#include "argv-util.h"
#include "dirent-util.h"
#include "env-file.h"
#include "env-util.h"
#include "errno-util.h"
@@ -94,7 +95,7 @@ static int get_process_state(pid_t pid) {
return (unsigned char) state;
}
int get_process_comm(pid_t pid, char **ret) {
int pid_get_comm(pid_t pid, char **ret) {
_cleanup_free_ char *escaped = NULL, *comm = NULL;
int r;
@@ -132,15 +133,35 @@ int get_process_comm(pid_t pid, char **ret) {
return 0;
}
static int get_process_cmdline_nulstr(
int pidref_get_comm(const PidRef *pid, char **ret) {
_cleanup_free_ char *comm = NULL;
int r;
if (!pidref_is_set(pid))
return -ESRCH;
r = pid_get_comm(pid->pid, &comm);
if (r < 0)
return r;
r = pidref_verify(pid);
if (r < 0)
return r;
if (ret)
*ret = TAKE_PTR(comm);
return 0;
}
static int pid_get_cmdline_nulstr(
pid_t pid,
size_t max_size,
ProcessCmdlineFlags flags,
char **ret,
size_t *ret_size) {
_cleanup_free_ char *t = NULL;
const char *p;
char *t;
size_t k;
int r;
@@ -164,18 +185,17 @@ static int get_process_cmdline_nulstr(
return r;
if (k == 0) {
t = mfree(t);
if (!(flags & PROCESS_CMDLINE_COMM_FALLBACK))
return -ENOENT;
/* Kernel threads have no argv[] */
_cleanup_free_ char *comm = NULL;
r = get_process_comm(pid, &comm);
r = pid_get_comm(pid, &comm);
if (r < 0)
return r;
free(t);
t = strjoin("[", comm, "]");
if (!t)
return -ENOMEM;
@@ -186,12 +206,15 @@ static int get_process_cmdline_nulstr(
t[max_size] = '\0';
}
*ret = t;
*ret_size = k;
if (ret)
*ret = TAKE_PTR(t);
if (ret_size)
*ret_size = k;
return r;
}
int get_process_cmdline(pid_t pid, size_t max_columns, ProcessCmdlineFlags flags, char **ret) {
int pid_get_cmdline(pid_t pid, size_t max_columns, ProcessCmdlineFlags flags, char **ret) {
_cleanup_free_ char *t = NULL;
size_t k;
char *ans;
@@ -213,7 +236,7 @@ int get_process_cmdline(pid_t pid, size_t max_columns, ProcessCmdlineFlags flags
* Returns -ESRCH if the process doesn't exist, and -ENOENT if the process has no command line (and
* PROCESS_CMDLINE_COMM_FALLBACK is not specified). Returns 0 and sets *line otherwise. */
int full = get_process_cmdline_nulstr(pid, max_columns, flags, &t, &k);
int full = pid_get_cmdline_nulstr(pid, max_columns, flags, &t, &k);
if (full < 0)
return full;
@@ -256,7 +279,27 @@ int get_process_cmdline(pid_t pid, size_t max_columns, ProcessCmdlineFlags flags
return 0;
}
int get_process_cmdline_strv(pid_t pid, ProcessCmdlineFlags flags, char ***ret) {
int pidref_get_cmdline(const PidRef *pid, size_t max_columns, ProcessCmdlineFlags flags, char **ret) {
_cleanup_free_ char *s = NULL;
int r;
if (!pidref_is_set(pid))
return -ESRCH;
r = pid_get_cmdline(pid->pid, max_columns, flags, &s);
if (r < 0)
return r;
r = pidref_verify(pid);
if (r < 0)
return r;
if (ret)
*ret = TAKE_PTR(s);
return 0;
}
int pid_get_cmdline_strv(pid_t pid, ProcessCmdlineFlags flags, char ***ret) {
_cleanup_free_ char *t = NULL;
char **args;
size_t k;
@@ -266,7 +309,7 @@ int get_process_cmdline_strv(pid_t pid, ProcessCmdlineFlags flags, char ***ret)
assert((flags & ~PROCESS_CMDLINE_COMM_FALLBACK) == 0);
assert(ret);
r = get_process_cmdline_nulstr(pid, SIZE_MAX, flags, &t, &k);
r = pid_get_cmdline_nulstr(pid, SIZE_MAX, flags, &t, &k);
if (r < 0)
return r;
@@ -278,6 +321,27 @@ int get_process_cmdline_strv(pid_t pid, ProcessCmdlineFlags flags, char ***ret)
return 0;
}
int pidref_get_cmdline_strv(const PidRef *pid, ProcessCmdlineFlags flags, char ***ret) {
_cleanup_strv_free_ char **args = NULL;
int r;
if (!pidref_is_set(pid))
return -ESRCH;
r = pid_get_cmdline_strv(pid->pid, flags, &args);
if (r < 0)
return r;
r = pidref_verify(pid);
if (r < 0)
return r;
if (ret)
*ret = TAKE_PTR(args);
return 0;
}
int container_get_leader(const char *machine, pid_t *pid) {
_cleanup_free_ char *s = NULL, *class = NULL;
const char *p;
@@ -346,7 +410,7 @@ int namespace_get_leader(pid_t pid, NamespaceType type, pid_t *ret) {
}
}
int is_kernel_thread(pid_t pid) {
int pid_is_kernel_thread(pid_t pid) {
_cleanup_free_ char *line = NULL;
unsigned long long flags;
size_t l, i;
@@ -404,6 +468,23 @@ int is_kernel_thread(pid_t pid) {
return !!(flags & PF_KTHREAD);
}
int pidref_is_kernel_thread(const PidRef *pid) {
int result, r;
if (!pidref_is_set(pid))
return -ESRCH;
result = pid_is_kernel_thread(pid->pid);
if (result < 0)
return result;
r = pidref_verify(pid); /* Verify that the PID wasn't reused since */
if (r < 0)
return r;
return result;
}
int get_process_capeff(pid_t pid, char **ret) {
const char *p;
int r;
@@ -492,7 +573,8 @@ static int get_process_id(pid_t pid, const char *field, uid_t *ret) {
return -EIO;
}
int get_process_uid(pid_t pid, uid_t *ret) {
int pid_get_uid(pid_t pid, uid_t *ret) {
assert(ret);
if (pid == 0 || pid == getpid_cached()) {
*ret = getuid();
@@ -502,6 +584,26 @@ int get_process_uid(pid_t pid, uid_t *ret) {
return get_process_id(pid, "Uid:", ret);
}
int pidref_get_uid(const PidRef *pid, uid_t *ret) {
uid_t uid;
int r;
if (!pidref_is_set(pid))
return -ESRCH;
r = pid_get_uid(pid->pid, &uid);
if (r < 0)
return r;
r = pidref_verify(pid);
if (r < 0)
return r;
if (ret)
*ret = uid;
return 0;
}
int get_process_gid(pid_t pid, gid_t *ret) {
if (pid == 0 || pid == getpid_cached()) {
@@ -692,7 +794,7 @@ int wait_for_terminate_and_check(const char *name, pid_t pid, WaitFlags flags) {
assert(pid > 1);
if (!name) {
r = get_process_comm(pid, &buffer);
r = pid_get_comm(pid, &buffer);
if (r < 0)
log_debug_errno(r, "Failed to acquire process name of " PID_FMT ", ignoring: %m", pid);
else
@@ -914,6 +1016,9 @@ int pid_is_my_child(pid_t pid) {
pid_t ppid;
int r;
if (pid < 0)
return -ESRCH;
if (pid <= 1)
return false;
@@ -924,11 +1029,28 @@ int pid_is_my_child(pid_t pid) {
return ppid == getpid_cached();
}
bool pid_is_unwaited(pid_t pid) {
int pidref_is_my_child(const PidRef *pid) {
int r, result;
if (!pidref_is_set(pid))
return -ESRCH;
result = pid_is_my_child(pid->pid);
if (result < 0)
return result;
r = pidref_verify(pid);
if (r < 0)
return r;
return result;
}
int pid_is_unwaited(pid_t pid) {
/* Checks whether a PID is still valid at all, including a zombie */
if (pid < 0)
return false;
return -ESRCH;
if (pid <= 1) /* If we or PID 1 would be dead and have been waited for, this code would not be running */
return true;
@@ -942,13 +1064,31 @@ bool pid_is_unwaited(pid_t pid) {
return errno != ESRCH;
}
bool pid_is_alive(pid_t pid) {
int pidref_is_unwaited(const PidRef *pid) {
int r;
if (!pidref_is_set(pid))
return -ESRCH;
if (pid->pid == 1 || pidref_is_self(pid))
return true;
r = pidref_kill(pid, 0);
if (r == -ESRCH)
return false;
if (r < 0)
return r;
return true;
}
int pid_is_alive(pid_t pid) {
int r;
/* Checks whether a PID is still valid and not a zombie */
if (pid < 0)
return false;
return -ESRCH;
if (pid <= 1) /* If we or PID 1 would be a zombie, this code would not be running */
return true;
@@ -957,10 +1097,31 @@ bool pid_is_alive(pid_t pid) {
return true;
r = get_process_state(pid);
if (IN_SET(r, -ESRCH, 'Z'))
if (r == -ESRCH)
return false;
if (r < 0)
return r;
return true;
return r != 'Z';
}
int pidref_is_alive(const PidRef *pidref) {
int r, result;
if (!pidref_is_set(pidref))
return -ESRCH;
result = pid_is_alive(pidref->pid);
if (result < 0)
return result;
r = pidref_verify(pidref);
if (r == -ESRCH)
return false;
if (r < 0)
return r;
return result;
}
int pid_from_same_root_fs(pid_t pid) {
@@ -1803,6 +1964,74 @@ fail:
return -r;
}
int proc_dir_open(DIR **ret) {
DIR *d;
assert(ret);
d = opendir("/proc");
if (!d)
return -errno;
*ret = d;
return 0;
}
int proc_dir_read(DIR *d, pid_t *ret) {
assert(d);
for (;;) {
struct dirent *de;
errno = 0;
de = readdir_no_dot(d);
if (!de) {
if (errno != 0)
return -errno;
break;
}
if (!IN_SET(de->d_type, DT_DIR, DT_UNKNOWN))
continue;
if (parse_pid(de->d_name, ret) >= 0)
return 1;
}
if (ret)
*ret = 0;
return 0;
}
int proc_dir_read_pidref(DIR *d, PidRef *ret) {
int r;
assert(d);
for (;;) {
pid_t pid;
r = proc_dir_read(d, &pid);
if (r < 0)
return r;
if (r == 0)
break;
r = pidref_set_pid(ret, pid);
if (r == -ESRCH) /* gone by now? skip it */
continue;
if (r < 0)
return r;
return 1;
}
if (ret)
*ret = PIDREF_NULL;
return 0;
}
static const char *const sigchld_code_table[] = {
[CLD_EXITED] = "exited",
[CLD_KILLED] = "killed",
+19 -7
View File
@@ -39,11 +39,15 @@ typedef enum ProcessCmdlineFlags {
PROCESS_CMDLINE_QUOTE_POSIX = 1 << 3,
} ProcessCmdlineFlags;
int get_process_comm(pid_t pid, char **ret);
int get_process_cmdline(pid_t pid, size_t max_columns, ProcessCmdlineFlags flags, char **ret);
int get_process_cmdline_strv(pid_t pid, ProcessCmdlineFlags flags, char ***ret);
int pid_get_comm(pid_t pid, char **ret);
int pidref_get_comm(const PidRef *pid, char **ret);
int pid_get_cmdline(pid_t pid, size_t max_columns, ProcessCmdlineFlags flags, char **ret);
int pidref_get_cmdline(const PidRef *pid, size_t max_columns, ProcessCmdlineFlags flags, char **ret);
int pid_get_cmdline_strv(pid_t pid, ProcessCmdlineFlags flags, char ***ret);
int pidref_get_cmdline_strv(const PidRef *pid, ProcessCmdlineFlags flags, char ***ret);
int get_process_exe(pid_t pid, char **ret);
int get_process_uid(pid_t pid, uid_t *ret);
int pid_get_uid(pid_t pid, uid_t *ret);
int pidref_get_uid(const PidRef *pid, uid_t *ret);
int get_process_gid(pid_t pid, gid_t *ret);
int get_process_capeff(pid_t pid, char **ret);
int get_process_cwd(pid_t pid, char **ret);
@@ -77,13 +81,17 @@ void sigkill_nowaitp(pid_t *pid);
int kill_and_sigcont(pid_t pid, int sig);
int is_kernel_thread(pid_t pid);
int pid_is_kernel_thread(pid_t pid);
int pidref_is_kernel_thread(const PidRef *pid);
int getenv_for_pid(pid_t pid, const char *field, char **_value);
bool pid_is_alive(pid_t pid);
bool pid_is_unwaited(pid_t pid);
int pid_is_alive(pid_t pid);
int pidref_is_alive(const PidRef *pidref);
int pid_is_unwaited(pid_t pid);
int pidref_is_unwaited(const PidRef *pidref);
int pid_is_my_child(pid_t pid);
int pidref_is_my_child(const PidRef *pidref);
int pid_from_same_root_fs(pid_t pid);
bool is_main_thread(void);
@@ -215,3 +223,7 @@ int is_reaper_process(void);
int make_reaper_process(bool b);
int posix_spawn_wrapper(const char *path, char *const *argv, char *const *envp, pid_t *ret_pid);
int proc_dir_open(DIR **ret);
int proc_dir_read(DIR *d, pid_t *ret);
int proc_dir_read_pidref(DIR *d, PidRef *ret);