diff options
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/busname.c | 10 | ||||
-rw-r--r-- | src/core/dbus-manager.c | 25 | ||||
-rw-r--r-- | src/core/dbus-unit.c | 143 | ||||
-rw-r--r-- | src/core/dbus-unit.h | 1 | ||||
-rw-r--r-- | src/core/mount.c | 10 | ||||
-rw-r--r-- | src/core/org.freedesktop.systemd1.conf | 4 | ||||
-rw-r--r-- | src/core/service.c | 19 | ||||
-rw-r--r-- | src/core/socket.c | 10 | ||||
-rw-r--r-- | src/core/swap.c | 10 | ||||
-rw-r--r-- | src/core/unit.c | 18 | ||||
-rw-r--r-- | src/core/unit.h | 9 |
11 files changed, 259 insertions, 0 deletions
diff --git a/src/core/busname.c b/src/core/busname.c index bbe61af4f0..f4f433340c 100644 --- a/src/core/busname.c +++ b/src/core/busname.c @@ -999,6 +999,14 @@ static bool busname_supported(void) { return supported; } +static int busname_control_pid(Unit *u) { + BusName *n = BUSNAME(u); + + assert(n); + + return n->control_pid; +} + static const char* const busname_result_table[_BUSNAME_RESULT_MAX] = { [BUSNAME_SUCCESS] = "success", [BUSNAME_FAILURE_RESOURCES] = "resources", @@ -1052,6 +1060,8 @@ const UnitVTable busname_vtable = { .supported = busname_supported, + .control_pid = busname_control_pid, + .bus_vtable = bus_busname_vtable, .status_message_formats = { diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c index 0c86791fe3..d2eb388f7c 100644 --- a/src/core/dbus-manager.c +++ b/src/core/dbus-manager.c @@ -642,6 +642,30 @@ static int method_set_unit_properties(sd_bus_message *message, void *userdata, s return bus_unit_method_set_properties(message, u, error); } +static int method_get_unit_processes(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + const char *name; + Unit *u; + int r; + + assert(message); + assert(m); + + r = sd_bus_message_read(message, "s", &name); + if (r < 0) + return r; + + r = manager_load_unit(m, name, NULL, error, &u); + if (r < 0) + return r; + + r = bus_unit_check_load_state(u, error); + if (r < 0) + return r; + + return bus_unit_method_get_processes(message, u, error); +} + static int transient_unit_from_message( Manager *m, sd_bus_message *message, @@ -2042,6 +2066,7 @@ const sd_bus_vtable bus_manager_vtable[] = { SD_BUS_METHOD("ResetFailedUnit", "s", NULL, method_reset_failed_unit, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("SetUnitProperties", "sba(sv)", NULL, method_set_unit_properties, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("StartTransientUnit", "ssa(sv)a(sa(sv))", "o", method_start_transient_unit, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetUnitProcesses", "s", "a(sus)", method_get_unit_processes, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("GetJob", "u", "o", method_get_job, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("CancelJob", "u", NULL, method_cancel_job, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("ClearJobs", NULL, NULL, method_clear_jobs, SD_BUS_VTABLE_UNPRIVILEGED), diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c index c507265070..ed207f15b9 100644 --- a/src/core/dbus-unit.c +++ b/src/core/dbus-unit.c @@ -24,8 +24,10 @@ #include "cgroup-util.h" #include "dbus-unit.h" #include "dbus.h" +#include "fd-util.h" #include "locale-util.h" #include "log.h" +#include "process-util.h" #include "selinux-access.h" #include "signal-util.h" #include "special.h" @@ -841,6 +843,146 @@ static int property_get_cgroup( return sd_bus_message_append(reply, "s", t); } +static int append_process(sd_bus_message *reply, const char *p, pid_t pid, Set *pids) { + _cleanup_free_ char *buf = NULL, *cmdline = NULL; + int r; + + assert(reply); + assert(pid > 0); + + r = set_put(pids, PID_TO_PTR(pid)); + if (r == -EEXIST || r == 0) + return 0; + if (r < 0) + return r; + + if (!p) { + r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &buf); + if (r == -ESRCH) + return 0; + if (r < 0) + return r; + + p = buf; + } + + (void) get_process_cmdline(pid, 0, true, &cmdline); + + return sd_bus_message_append(reply, + "(sus)", + p, + (uint32_t) pid, + cmdline); +} + +static int append_cgroup(sd_bus_message *reply, const char *p, Set *pids) { + _cleanup_closedir_ DIR *d = NULL; + _cleanup_fclose_ FILE *f = NULL; + int r; + + assert(reply); + assert(p); + + r = cg_enumerate_processes(SYSTEMD_CGROUP_CONTROLLER, p, &f); + if (r == ENOENT) + return 0; + if (r < 0) + return r; + + for (;;) { + pid_t pid; + + r = cg_read_pid(f, &pid); + if (r < 0) + return r; + if (r == 0) + break; + + if (is_kernel_thread(pid) > 0) + continue; + + r = append_process(reply, p, pid, pids); + if (r < 0) + return r; + } + + r = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, p, &d); + if (r == -ENOENT) + return 0; + if (r < 0) + return r; + + for (;;) { + _cleanup_free_ char *g = NULL, *j = NULL; + + r = cg_read_subgroup(d, &g); + if (r < 0) + return r; + if (r == 0) + break; + + j = strjoin(p, "/", g, NULL); + if (!j) + return -ENOMEM; + + r = append_cgroup(reply, j, pids); + if (r < 0) + return r; + } + + return 0; +} + +int bus_unit_method_get_processes(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_(set_freep) Set *pids = NULL; + _cleanup_free_ char *p = NULL; + Unit *u = userdata; + pid_t pid; + int r; + + assert(message); + + pids = set_new(NULL); + if (!pids) + return -ENOMEM; + + r = sd_bus_message_new_method_return(message, &reply); + if (r < 0) + return r; + + r = sd_bus_message_open_container(reply, 'a', "(sus)"); + if (r < 0) + return r; + + if (u->cgroup_path) { + r = append_cgroup(reply, u->cgroup_path, pids); + if (r < 0) + return r; + } + + /* The main and control pids might live outside of the cgroup, hence fetch them separately */ + pid = unit_main_pid(u); + if (pid > 0) { + r = append_process(reply, NULL, pid, pids); + if (r < 0) + return r; + } + + pid = unit_control_pid(u); + if (pid > 0) { + r = append_process(reply, NULL, pid, pids); + if (r < 0) + return r; + } + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + + return sd_bus_send(NULL, reply, NULL); +} + const sd_bus_vtable bus_unit_cgroup_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("Slice", "s", property_get_slice, 0, 0), @@ -848,6 +990,7 @@ const sd_bus_vtable bus_unit_cgroup_vtable[] = { SD_BUS_PROPERTY("MemoryCurrent", "t", property_get_current_memory, 0, 0), SD_BUS_PROPERTY("CPUUsageNSec", "t", property_get_cpu_usage, 0, 0), SD_BUS_PROPERTY("TasksCurrent", "t", property_get_current_tasks, 0, 0), + SD_BUS_METHOD("GetProcesses", NULL, "a(sus)", bus_unit_method_get_processes, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_VTABLE_END }; diff --git a/src/core/dbus-unit.h b/src/core/dbus-unit.h index 07948b9cd0..4db88dbebc 100644 --- a/src/core/dbus-unit.h +++ b/src/core/dbus-unit.h @@ -36,5 +36,6 @@ int bus_unit_method_reset_failed(sd_bus_message *message, void *userdata, sd_bus int bus_unit_queue_job(sd_bus_message *message, Unit *u, JobType type, JobMode mode, bool reload_if_possible, sd_bus_error *error); int bus_unit_set_properties(Unit *u, sd_bus_message *message, UnitSetPropertiesMode mode, bool commit, sd_bus_error *error); int bus_unit_method_set_properties(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_unit_method_get_processes(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_unit_check_load_state(Unit *u, sd_bus_error *error); diff --git a/src/core/mount.c b/src/core/mount.c index 632c5c824c..188fb0aa40 100644 --- a/src/core/mount.c +++ b/src/core/mount.c @@ -1790,6 +1790,14 @@ static int mount_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) { return unit_kill_common(u, who, signo, -1, MOUNT(u)->control_pid, error); } +static int mount_control_pid(Unit *u) { + Mount *m = MOUNT(u); + + assert(m); + + return m->control_pid; +} + static const char* const mount_exec_command_table[_MOUNT_EXEC_COMMAND_MAX] = { [MOUNT_EXEC_MOUNT] = "ExecMount", [MOUNT_EXEC_UNMOUNT] = "ExecUnmount", @@ -1851,6 +1859,8 @@ const UnitVTable mount_vtable = { .reset_failed = mount_reset_failed, + .control_pid = mount_control_pid, + .bus_vtable = bus_mount_vtable, .bus_set_property = bus_mount_set_property, .bus_commit_properties = bus_mount_commit_properties, diff --git a/src/core/org.freedesktop.systemd1.conf b/src/core/org.freedesktop.systemd1.conf index f78eedbd6e..b732501364 100644 --- a/src/core/org.freedesktop.systemd1.conf +++ b/src/core/org.freedesktop.systemd1.conf @@ -78,6 +78,10 @@ <allow send_destination="org.freedesktop.systemd1" send_interface="org.freedesktop.systemd1.Manager" + send_member="GetUnitProcesses"/> + + <allow send_destination="org.freedesktop.systemd1" + send_interface="org.freedesktop.systemd1.Manager" send_member="ListJobs"/> <allow send_destination="org.freedesktop.systemd1" diff --git a/src/core/service.c b/src/core/service.c index 58084e2f82..b46dd8bcdd 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -3195,6 +3195,22 @@ static int service_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) { return unit_kill_common(u, who, signo, s->main_pid, s->control_pid, error); } +static int service_main_pid(Unit *u) { + Service *s = SERVICE(u); + + assert(s); + + return s->main_pid; +} + +static int service_control_pid(Unit *u) { + Service *s = SERVICE(u); + + assert(s); + + return s->control_pid; +} + static const char* const service_restart_table[_SERVICE_RESTART_MAX] = { [SERVICE_RESTART_NO] = "no", [SERVICE_RESTART_ON_SUCCESS] = "on-success", @@ -3303,6 +3319,9 @@ const UnitVTable service_vtable = { .notify_cgroup_empty = service_notify_cgroup_empty_event, .notify_message = service_notify_message, + .main_pid = service_main_pid, + .control_pid = service_control_pid, + .bus_name_owner_change = service_bus_name_owner_change, .bus_vtable = bus_service_vtable, diff --git a/src/core/socket.c b/src/core/socket.c index 65da0e3c5e..a9fff9c259 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -2781,6 +2781,14 @@ char *socket_fdname(Socket *s) { return UNIT(s)->id; } +static int socket_control_pid(Unit *u) { + Socket *s = SOCKET(u); + + assert(s); + + return s->control_pid; +} + static const char* const socket_exec_command_table[_SOCKET_EXEC_COMMAND_MAX] = { [SOCKET_EXEC_START_PRE] = "StartPre", [SOCKET_EXEC_START_CHOWN] = "StartChown", @@ -2846,6 +2854,8 @@ const UnitVTable socket_vtable = { .reset_failed = socket_reset_failed, + .control_pid = socket_control_pid, + .bus_vtable = bus_socket_vtable, .bus_set_property = bus_socket_set_property, .bus_commit_properties = bus_socket_commit_properties, diff --git a/src/core/swap.c b/src/core/swap.c index c6502eb821..d8802470d2 100644 --- a/src/core/swap.c +++ b/src/core/swap.c @@ -1426,6 +1426,14 @@ static bool swap_supported(void) { return supported; } +static int swap_control_pid(Unit *u) { + Swap *s = SWAP(u); + + assert(s); + + return s->control_pid; +} + static const char* const swap_exec_command_table[_SWAP_EXEC_COMMAND_MAX] = { [SWAP_EXEC_ACTIVATE] = "ExecActivate", [SWAP_EXEC_DEACTIVATE] = "ExecDeactivate", @@ -1487,6 +1495,8 @@ const UnitVTable swap_vtable = { .reset_failed = swap_reset_failed, + .control_pid = swap_control_pid, + .bus_vtable = bus_swap_vtable, .bus_set_property = bus_swap_set_property, .bus_commit_properties = bus_swap_commit_properties, diff --git a/src/core/unit.c b/src/core/unit.c index 1f57293a0b..cb79c7c6b1 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -3801,3 +3801,21 @@ bool unit_is_pristine(Unit *u) { u->job || u->merged_into); } + +pid_t unit_control_pid(Unit *u) { + assert(u); + + if (UNIT_VTABLE(u)->control_pid) + return UNIT_VTABLE(u)->control_pid(u); + + return 0; +} + +pid_t unit_main_pid(Unit *u) { + assert(u); + + if (UNIT_VTABLE(u)->main_pid) + return UNIT_VTABLE(u)->main_pid(u); + + return 0; +} diff --git a/src/core/unit.h b/src/core/unit.h index cfdac852a5..5909652976 100644 --- a/src/core/unit.h +++ b/src/core/unit.h @@ -390,6 +390,12 @@ struct UnitVTable { /* Returns the next timeout of a unit */ int (*get_timeout)(Unit *u, usec_t *timeout); + /* Returns the main PID if there is any defined, or 0. */ + pid_t (*main_pid)(Unit *u); + + /* Returns the main PID if there is any defined, or 0. */ + pid_t (*control_pid)(Unit *u); + /* This is called for each unit type and should be used to * enumerate existing devices and load them. However, * everything that is loaded here should still stay in @@ -601,6 +607,9 @@ bool unit_type_supported(UnitType t); bool unit_is_pristine(Unit *u); +pid_t unit_control_pid(Unit *u); +pid_t unit_main_pid(Unit *u); + static inline bool unit_supported(Unit *u) { return unit_type_supported(u->type); } |