Skip to content

Commit

Permalink
Merge pull request #29142 from poettering/pidref
Browse files Browse the repository at this point in the history
core: first step towards a pidfd focused future
  • Loading branch information
bluca committed Sep 9, 2023
2 parents 3cdf786 + a1f7cdc commit 5cd4613
Show file tree
Hide file tree
Showing 27 changed files with 564 additions and 271 deletions.
21 changes: 16 additions & 5 deletions TODO
Expand Up @@ -122,9 +122,6 @@ Deprecations and removals:
* drop fd_is_mount_point() fallback mess once we can rely on
STATX_ATTR_MOUNT_ROOT to exist i.e. kernel baseline 5.8

* rework our PID tracking in services and so on, to be strictly based on pidfd,
once kernel baseline is 5.13.

* Remove /dev/mem ACPI FPDT parsing when /sys/firmware/acpi/fpdt is ubiquitous.
That requires distros to enable CONFIG_ACPI_FPDT, and have kernels v5.12 for
x86 and v6.2 for arm.
Expand All @@ -136,6 +133,22 @@ Deprecations and removals:

Features:

* PidRef conversion work:
- pid_is_unwaited() → pidref_is_unwaited()
- pid_is_alive() → pidref_is_alive()
- unit_watch_pid() → unit_watch_pidref()
- unit_kill_common()
- unit_kill_context()
- service_set_main_pid()
- actually wait for POLLIN on piref's pidfd in service logic
- unit_main_pid() + unit_control_pid()
- exec_spawn()
- serialization of control/main pid in service, socket, mount, swap units
- unit_fork_and_watch_rm_rf()
- cg_pid_get_unit()
- openpt_allocate_in_namespace()
- scope dbus PIDs property needs to gain PIDFDs companion

* ddi must be listed as block device fstype

* measure some string via pcrphase whenever we end up booting into emergency
Expand Down Expand Up @@ -1281,8 +1294,6 @@ Features:

* if /usr/bin/swapoff fails due to OOM, log a friendly explanatory message about it

* pid1: Move to tracking of main pid/control pid of units per pidfd

* pid1: support new clone3() fork-into-cgroup feature

* pid1: also remove PID files of a service when the service starts, not just
Expand Down
1 change: 1 addition & 0 deletions src/basic/meson.build
Expand Up @@ -65,6 +65,7 @@ basic_sources = files(
'path-lookup.c',
'path-util.c',
'percent-util.c',
'pidref.c',
'prioq.c',
'proc-cmdline.c',
'process-util.c',
Expand Down
145 changes: 145 additions & 0 deletions src/basic/pidref.c
@@ -0,0 +1,145 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */

#include "errno-util.h"
#include "fd-util.h"
#include "missing_syscall.h"
#include "parse-util.h"
#include "pidref.h"
#include "process-util.h"

int pidref_set_pid(PidRef *pidref, pid_t pid) {
int fd;

assert(pidref);

if (pid < 0)
return -ESRCH;
if (pid == 0)
pid = getpid_cached();

fd = pidfd_open(pid, 0);
if (fd < 0) {
/* Graceful fallback in case the kernel doesn't support pidfds or is out of fds */
if (!ERRNO_IS_NOT_SUPPORTED(errno) && !ERRNO_IS_PRIVILEGE(errno) && !ERRNO_IS_RESOURCE(errno))
return -errno;

fd = -EBADF;
}

*pidref = (PidRef) {
.fd = fd,
.pid = pid,
};

return 0;
}

int pidref_set_pidstr(PidRef *pidref, const char *pid) {
pid_t nr;
int r;

assert(pidref);

r = parse_pid(pid, &nr);
if (r < 0)
return r;

return pidref_set_pid(pidref, nr);
}

int pidref_set_pidfd(PidRef *pidref, int fd) {
int r;

assert(pidref);

if (fd < 0)
return -EBADF;

int fd_copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
if (fd_copy < 0) {
pid_t pid;

if (!ERRNO_IS_RESOURCE(errno))
return -errno;

/* Graceful fallback if we are out of fds */
r = pidfd_get_pid(fd, &pid);
if (r < 0)
return r;

*pidref = (PidRef) {
.fd = -EBADF,
.pid = pid,
};

return 0;
}

return pidref_set_pidfd_consume(pidref, fd_copy);
}

int pidref_set_pidfd_take(PidRef *pidref, int fd) {
pid_t pid;
int r;

assert(pidref);

if (fd < 0)
return -EBADF;

r = pidfd_get_pid(fd, &pid);
if (r < 0)
return r;

*pidref = (PidRef) {
.fd = fd,
.pid = pid,
};

return 0;
}

int pidref_set_pidfd_consume(PidRef *pidref, int fd) {
int r;

r = pidref_set_pidfd_take(pidref, fd);
if (r < 0)
safe_close(fd);

return r;
}

void pidref_done(PidRef *pidref) {
assert(pidref);

*pidref = (PidRef) {
.fd = safe_close(pidref->fd),
};
}

int pidref_kill(PidRef *pidref, int sig) {

if (!pidref)
return -ESRCH;

if (pidref->fd >= 0)
return RET_NERRNO(pidfd_send_signal(pidref->fd, sig, NULL, 0));

if (pidref->pid > 0)
return RET_NERRNO(kill(pidref->pid, sig));

return -ESRCH;
}

int pidref_kill_and_sigcont(PidRef *pidref, int sig) {
int r;

r = pidref_kill(pidref, sig);
if (r < 0)
return r;

if (!IN_SET(sig, SIGCONT, SIGKILL))
(void) pidref_kill(pidref, SIGCONT);

return 0;
}
29 changes: 29 additions & 0 deletions src/basic/pidref.h
@@ -0,0 +1,29 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once

#include "macro.h"

/* An embeddable structure carrying a reference to a process. Supposed to be used when tracking processes continously. */
typedef struct PidRef {
pid_t pid; /* always valid */
int fd; /* only valid if pidfd are available in the kernel, and we manage to get an fd */
} PidRef;

#define PIDREF_NULL (PidRef) { .fd = -EBADF }

static inline bool pidref_is_set(const PidRef *pidref) {
return pidref && pidref->pid > 0;
}

int pidref_set_pid(PidRef *pidref, pid_t pid);
int pidref_set_pidstr(PidRef *pidref, const char *pid);
int pidref_set_pidfd(PidRef *pidref, int fd);
int pidref_set_pidfd_take(PidRef *pidref, int fd); /* takes ownership of the passed pidfd on success*/
int pidref_set_pidfd_consume(PidRef *pidref, int fd); /* takes ownership of the passed pidfd in both success and failure */

void pidref_done(PidRef *pidref);

int pidref_kill(PidRef *pidref, int sig);
int pidref_kill_and_sigcont(PidRef *pidref, int sig);

#define TAKE_PIDREF(p) TAKE_GENERIC((p), PidRef, PIDREF_NULL)
2 changes: 1 addition & 1 deletion src/core/dbus-mount.c
Expand Up @@ -89,7 +89,7 @@ const sd_bus_vtable bus_mount_vtable[] = {
SD_BUS_PROPERTY("Options","s", property_get_options, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("Type", "s", property_get_type, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("TimeoutUSec", "t", bus_property_get_usec, offsetof(Mount, timeout_usec), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("ControlPID", "u", bus_property_get_pid, offsetof(Mount, control_pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("ControlPID", "u", bus_property_get_pid, offsetof(Mount, control_pid.pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("DirectoryMode", "u", bus_property_get_mode, offsetof(Mount, directory_mode), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("SloppyOptions", "b", bus_property_get_bool, offsetof(Mount, sloppy_options), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("LazyUnmount", "b", bus_property_get_bool, offsetof(Mount, lazy_unmount), SD_BUS_VTABLE_PROPERTY_CONST),
Expand Down
4 changes: 2 additions & 2 deletions src/core/dbus-service.c
Expand Up @@ -346,8 +346,8 @@ const sd_bus_vtable bus_service_vtable[] = {
SD_BUS_PROPERTY("RestartPreventExitStatus", "(aiai)", property_get_exit_status_set, offsetof(Service, restart_prevent_status), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("RestartForceExitStatus", "(aiai)", property_get_exit_status_set, offsetof(Service, restart_force_status), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("SuccessExitStatus", "(aiai)", property_get_exit_status_set, offsetof(Service, success_status), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("MainPID", "u", bus_property_get_pid, offsetof(Service, main_pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("ControlPID", "u", bus_property_get_pid, offsetof(Service, control_pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("MainPID", "u", bus_property_get_pid, offsetof(Service, main_pid.pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("ControlPID", "u", bus_property_get_pid, offsetof(Service, control_pid.pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("BusName", "s", NULL, offsetof(Service, bus_name), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("FileDescriptorStoreMax", "u", bus_property_get_unsigned, offsetof(Service, n_fd_store_max), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("NFileDescriptorStore", "u", property_get_size_as_uint32, offsetof(Service, n_fd_store), 0),
Expand Down
2 changes: 1 addition & 1 deletion src/core/dbus-swap.c
Expand Up @@ -42,7 +42,7 @@ const sd_bus_vtable bus_swap_vtable[] = {
SD_BUS_PROPERTY("Priority", "i", property_get_priority, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("Options", "s", property_get_options, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("TimeoutUSec", "t", bus_property_get_usec, offsetof(Swap, timeout_usec), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("ControlPID", "u", bus_property_get_pid, offsetof(Swap, control_pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("ControlPID", "u", bus_property_get_pid, offsetof(Swap, control_pid.pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Swap, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("UID", "u", bus_property_get_uid, offsetof(Unit, ref_uid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("GID", "u", bus_property_get_gid, offsetof(Unit, ref_gid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
Expand Down

0 comments on commit 5cd4613

Please sign in to comment.