Merge pull request #1111 from poettering/more-cgroup-fixes
More cgroup fixes
This commit is contained in:
commit
fc94c32605
|
@ -29,7 +29,6 @@
|
|||
#include <sys/types.h>
|
||||
#include <ftw.h>
|
||||
|
||||
#include "cgroup-util.h"
|
||||
#include "set.h"
|
||||
#include "macro.h"
|
||||
#include "util.h"
|
||||
|
@ -41,6 +40,7 @@
|
|||
#include "special.h"
|
||||
#include "mkdir.h"
|
||||
#include "login-util.h"
|
||||
#include "cgroup-util.h"
|
||||
|
||||
int cg_enumerate_processes(const char *controller, const char *path, FILE **_f) {
|
||||
_cleanup_free_ char *fs = NULL;
|
||||
|
@ -113,7 +113,7 @@ int cg_read_subgroup(DIR *d, char **fn) {
|
|||
assert(d);
|
||||
assert(fn);
|
||||
|
||||
FOREACH_DIRENT(de, d, return -errno) {
|
||||
FOREACH_DIRENT_ALL(de, d, return -errno) {
|
||||
char *b;
|
||||
|
||||
if (de->d_type != DT_DIR)
|
||||
|
@ -197,7 +197,7 @@ int cg_kill(const char *controller, const char *path, int sig, bool sigcont, boo
|
|||
ret = -errno;
|
||||
} else {
|
||||
if (sigcont && sig != SIGKILL)
|
||||
kill(pid, SIGCONT);
|
||||
(void) kill(pid, SIGCONT);
|
||||
|
||||
if (ret == 0)
|
||||
ret = 1;
|
||||
|
@ -233,7 +233,7 @@ int cg_kill(const char *controller, const char *path, int sig, bool sigcont, boo
|
|||
int cg_kill_recursive(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, bool rem, Set *s) {
|
||||
_cleanup_set_free_ Set *allocated_set = NULL;
|
||||
_cleanup_closedir_ DIR *d = NULL;
|
||||
int r, ret = 0;
|
||||
int r, ret;
|
||||
char *fn;
|
||||
|
||||
assert(path);
|
||||
|
@ -264,7 +264,7 @@ int cg_kill_recursive(const char *controller, const char *path, int sig, bool si
|
|||
return -ENOMEM;
|
||||
|
||||
r = cg_kill_recursive(controller, p, sig, sigcont, ignore_self, rem, s);
|
||||
if (ret >= 0 && r != 0)
|
||||
if (r != 0 && ret >= 0)
|
||||
ret = r;
|
||||
}
|
||||
|
||||
|
@ -321,6 +321,14 @@ int cg_migrate(const char *cfrom, const char *pfrom, const char *cto, const char
|
|||
if (set_get(s, LONG_TO_PTR(pid)) == LONG_TO_PTR(pid))
|
||||
continue;
|
||||
|
||||
/* Ignore kernel threads. Since they can only
|
||||
* exist in the root cgroup, we only check for
|
||||
* them there. */
|
||||
if (cfrom &&
|
||||
(isempty(pfrom) || path_equal(pfrom, "/")) &&
|
||||
is_kernel_thread(pid) > 0)
|
||||
continue;
|
||||
|
||||
r = cg_attach(cto, pto, pid);
|
||||
if (r < 0) {
|
||||
if (ret >= 0 && r != -ESRCH)
|
||||
|
@ -382,12 +390,8 @@ int cg_migrate_recursive(
|
|||
|
||||
p = strjoin(pfrom, "/", fn, NULL);
|
||||
free(fn);
|
||||
if (!p) {
|
||||
if (ret >= 0)
|
||||
return -ENOMEM;
|
||||
|
||||
return ret;
|
||||
}
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
|
||||
r = cg_migrate_recursive(cfrom, p, cto, pto, ignore_self, rem);
|
||||
if (r != 0 && ret >= 0)
|
||||
|
@ -428,13 +432,15 @@ int cg_migrate_recursive_fallback(
|
|||
/* This didn't work? Then let's try all prefixes of the destination */
|
||||
|
||||
PATH_FOREACH_PREFIX(prefix, pto) {
|
||||
r = cg_migrate_recursive(cfrom, pfrom, cto, prefix, ignore_self, rem);
|
||||
if (r >= 0)
|
||||
break;
|
||||
int q;
|
||||
|
||||
q = cg_migrate_recursive(cfrom, pfrom, cto, prefix, ignore_self, rem);
|
||||
if (q >= 0)
|
||||
return q;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
static const char *normalize_controller(const char *controller) {
|
||||
|
@ -549,7 +555,7 @@ static int trim_cb(const char *path, const struct stat *sb, int typeflag, struct
|
|||
if (ftwbuf->level < 1)
|
||||
return 0;
|
||||
|
||||
rmdir(path);
|
||||
(void) rmdir(path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -564,8 +570,14 @@ int cg_trim(const char *controller, const char *path, bool delete_root) {
|
|||
return r;
|
||||
|
||||
errno = 0;
|
||||
if (nftw(fs, trim_cb, 64, FTW_DEPTH|FTW_MOUNT|FTW_PHYS) != 0)
|
||||
r = errno ? -errno : -EIO;
|
||||
if (nftw(fs, trim_cb, 64, FTW_DEPTH|FTW_MOUNT|FTW_PHYS) != 0) {
|
||||
if (errno == ENOENT)
|
||||
r = 0;
|
||||
else if (errno != 0)
|
||||
r = -errno;
|
||||
else
|
||||
r = -EIO;
|
||||
}
|
||||
|
||||
if (delete_root) {
|
||||
if (rmdir(fs) < 0 && errno != ENOENT)
|
||||
|
@ -664,13 +676,15 @@ int cg_attach_fallback(const char *controller, const char *path, pid_t pid) {
|
|||
* the destination */
|
||||
|
||||
PATH_FOREACH_PREFIX(prefix, path) {
|
||||
r = cg_attach(controller, prefix, pid);
|
||||
if (r >= 0)
|
||||
break;
|
||||
int q;
|
||||
|
||||
q = cg_attach(controller, prefix, pid);
|
||||
if (q >= 0)
|
||||
return q;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
int cg_set_group_access(
|
||||
|
@ -683,7 +697,8 @@ int cg_set_group_access(
|
|||
_cleanup_free_ char *fs = NULL;
|
||||
int r;
|
||||
|
||||
assert(path);
|
||||
if (mode == MODE_INVALID && uid == UID_INVALID && gid == GID_INVALID)
|
||||
return 0;
|
||||
|
||||
if (mode != MODE_INVALID)
|
||||
mode &= 0777;
|
||||
|
@ -819,7 +834,7 @@ int cg_install_release_agent(const char *controller, const char *agent) {
|
|||
return r;
|
||||
|
||||
sc = strstrip(contents);
|
||||
if (sc[0] == 0) {
|
||||
if (isempty(sc)) {
|
||||
r = write_string_file(fs, agent, 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -876,49 +891,46 @@ int cg_uninstall_release_agent(const char *controller) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int cg_is_empty(const char *controller, const char *path, bool ignore_self) {
|
||||
int cg_is_empty(const char *controller, const char *path) {
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
pid_t pid = 0, self_pid;
|
||||
bool found = false;
|
||||
pid_t pid = 0;
|
||||
int r;
|
||||
|
||||
assert(path);
|
||||
|
||||
r = cg_enumerate_processes(controller, path, &f);
|
||||
if (r < 0)
|
||||
return r == -ENOENT ? 1 : r;
|
||||
|
||||
self_pid = getpid();
|
||||
|
||||
while ((r = cg_read_pid(f, &pid)) > 0) {
|
||||
|
||||
if (ignore_self && pid == self_pid)
|
||||
continue;
|
||||
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (r == -ENOENT)
|
||||
return 1;
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return !found;
|
||||
r = cg_read_pid(f, &pid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return r == 0;
|
||||
}
|
||||
|
||||
int cg_is_empty_recursive(const char *controller, const char *path, bool ignore_self) {
|
||||
int cg_is_empty_recursive(const char *controller, const char *path) {
|
||||
_cleanup_closedir_ DIR *d = NULL;
|
||||
char *fn;
|
||||
int r;
|
||||
|
||||
assert(path);
|
||||
|
||||
r = cg_is_empty(controller, path, ignore_self);
|
||||
/* The root cgroup is always populated */
|
||||
if (controller && (isempty(path) || path_equal(path, "/")))
|
||||
return 0;
|
||||
|
||||
r = cg_is_empty(controller, path);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
r = cg_enumerate_subgroups(controller, path, &d);
|
||||
if (r == -ENOENT)
|
||||
return 1;
|
||||
if (r < 0)
|
||||
return r == -ENOENT ? 1 : r;
|
||||
return r;
|
||||
|
||||
while ((r = cg_read_subgroup(d, &fn)) > 0) {
|
||||
_cleanup_free_ char *p = NULL;
|
||||
|
@ -928,7 +940,7 @@ int cg_is_empty_recursive(const char *controller, const char *path, bool ignore_
|
|||
if (!p)
|
||||
return -ENOMEM;
|
||||
|
||||
r = cg_is_empty_recursive(controller, p, ignore_self);
|
||||
r = cg_is_empty_recursive(controller, p);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
}
|
||||
|
@ -1869,6 +1881,11 @@ int cg_kernel_controllers(Set *controllers) {
|
|||
|
||||
assert(controllers);
|
||||
|
||||
/* Determines the full list of kernel-known controllers. Might
|
||||
* include controllers we don't actually support, arbitrary
|
||||
* named hierarchies and controllers that aren't currently
|
||||
* accessible (because not mounted). */
|
||||
|
||||
f = fopen("/proc/cgroups", "re");
|
||||
if (!f) {
|
||||
if (errno == ENOENT)
|
||||
|
@ -1889,7 +1906,7 @@ int cg_kernel_controllers(Set *controllers) {
|
|||
if (feof(f))
|
||||
break;
|
||||
|
||||
if (ferror(f) && errno)
|
||||
if (ferror(f) && errno != 0)
|
||||
return -errno;
|
||||
|
||||
return -EBADMSG;
|
||||
|
|
|
@ -93,8 +93,8 @@ int cg_set_task_access(const char *controller, const char *path, mode_t mode, ui
|
|||
int cg_install_release_agent(const char *controller, const char *agent);
|
||||
int cg_uninstall_release_agent(const char *controller);
|
||||
|
||||
int cg_is_empty(const char *controller, const char *path, bool ignore_self);
|
||||
int cg_is_empty_recursive(const char *controller, const char *path, bool ignore_self);
|
||||
int cg_is_empty(const char *controller, const char *path);
|
||||
int cg_is_empty_recursive(const char *controller, const char *path);
|
||||
|
||||
int cg_get_root_path(char **path);
|
||||
|
||||
|
|
|
@ -28,12 +28,14 @@ Set *internal_set_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
|
|||
#define set_new(ops) internal_set_new(ops HASHMAP_DEBUG_SRC_ARGS)
|
||||
|
||||
|
||||
static inline void set_free(Set *s) {
|
||||
static inline Set *set_free(Set *s) {
|
||||
internal_hashmap_free(HASHMAP_BASE(s));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void set_free_free(Set *s) {
|
||||
static inline Set *set_free_free(Set *s) {
|
||||
internal_hashmap_free_free(HASHMAP_BASE(s));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* no set_free_free_free */
|
||||
|
|
|
@ -560,15 +560,17 @@ static void display(Hashmap *a) {
|
|||
path_columns = maxtpath;
|
||||
|
||||
for (j = 0; j < n; j++) {
|
||||
_cleanup_free_ char *p = NULL;
|
||||
_cleanup_free_ char *ellipsized = NULL;
|
||||
const char *path;
|
||||
|
||||
if (on_tty() && j + 5 > rows)
|
||||
break;
|
||||
|
||||
g = array[j];
|
||||
|
||||
p = ellipsize(g->path, path_columns, 33);
|
||||
printf("%-*s", path_columns, p ?: g->path);
|
||||
path = isempty(g->path) ? "/" : g->path;
|
||||
ellipsized = ellipsize(path, path_columns, 33);
|
||||
printf("%-*s", path_columns, ellipsized ?: path);
|
||||
|
||||
if (g->n_tasks_valid)
|
||||
printf(" %7u", g->n_tasks);
|
||||
|
|
|
@ -1005,6 +1005,7 @@ Unit* manager_get_unit_by_cgroup(Manager *m, const char *cgroup) {
|
|||
|
||||
Unit *manager_get_unit_by_pid(Manager *m, pid_t pid) {
|
||||
_cleanup_free_ char *cgroup = NULL;
|
||||
Unit *u;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
|
@ -1012,6 +1013,14 @@ Unit *manager_get_unit_by_pid(Manager *m, pid_t pid) {
|
|||
if (pid <= 1)
|
||||
return NULL;
|
||||
|
||||
u = hashmap_get(m->watch_pids1, LONG_TO_PTR(pid));
|
||||
if (u)
|
||||
return u;
|
||||
|
||||
u = hashmap_get(m->watch_pids2, LONG_TO_PTR(pid));
|
||||
if (u)
|
||||
return u;
|
||||
|
||||
r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &cgroup);
|
||||
if (r < 0)
|
||||
return NULL;
|
||||
|
@ -1030,7 +1039,7 @@ int manager_notify_cgroup_empty(Manager *m, const char *cgroup) {
|
|||
if (!u)
|
||||
return 0;
|
||||
|
||||
r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, true);
|
||||
r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
|
@ -1124,6 +1133,18 @@ int unit_reset_cpu_usage(Unit *u) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool unit_cgroup_delegate(Unit *u) {
|
||||
CGroupContext *c;
|
||||
|
||||
assert(u);
|
||||
|
||||
c = unit_get_cgroup_context(u);
|
||||
if (!c)
|
||||
return false;
|
||||
|
||||
return c->delegate;
|
||||
}
|
||||
|
||||
static const char* const cgroup_device_policy_table[_CGROUP_DEVICE_POLICY_MAX] = {
|
||||
[CGROUP_AUTO] = "auto",
|
||||
[CGROUP_CLOSED] = "closed",
|
||||
|
|
|
@ -130,5 +130,7 @@ int unit_get_memory_current(Unit *u, uint64_t *ret);
|
|||
int unit_get_cpu_usage(Unit *u, nsec_t *ret);
|
||||
int unit_reset_cpu_usage(Unit *u);
|
||||
|
||||
bool unit_cgroup_delegate(Unit *u);
|
||||
|
||||
const char* cgroup_device_policy_to_string(CGroupDevicePolicy i) _const_;
|
||||
CGroupDevicePolicy cgroup_device_policy_from_string(const char *s) _pure_;
|
||||
|
|
|
@ -2048,7 +2048,7 @@ finish:
|
|||
* kernel; at this point, we will not listen to the
|
||||
* signals anyway */
|
||||
if (detect_container(NULL) <= 0)
|
||||
cg_uninstall_release_agent(SYSTEMD_CGROUP_CONTROLLER);
|
||||
(void) cg_uninstall_release_agent(SYSTEMD_CGROUP_CONTROLLER);
|
||||
|
||||
execve(SYSTEMD_SHUTDOWN_BINARY_PATH, (char **) command_line, env_block);
|
||||
log_error_errno(errno, "Failed to execute shutdown binary, %s: %m",
|
||||
|
|
|
@ -573,6 +573,7 @@ int manager_new(ManagerRunningAs running_as, bool test_run, Manager **_m) {
|
|||
|
||||
m->ask_password_inotify_fd = -1;
|
||||
m->have_ask_password = -EINVAL; /* we don't know */
|
||||
m->first_boot = -1;
|
||||
|
||||
m->test_run = test_run;
|
||||
|
||||
|
@ -2998,12 +2999,14 @@ void manager_set_first_boot(Manager *m, bool b) {
|
|||
if (m->running_as != MANAGER_SYSTEM)
|
||||
return;
|
||||
|
||||
m->first_boot = b;
|
||||
if (m->first_boot != (int) b) {
|
||||
if (b)
|
||||
(void) touch("/run/systemd/first-boot");
|
||||
else
|
||||
(void) unlink("/run/systemd/first-boot");
|
||||
}
|
||||
|
||||
if (m->first_boot)
|
||||
touch("/run/systemd/first-boot");
|
||||
else
|
||||
unlink("/run/systemd/first-boot");
|
||||
m->first_boot = b;
|
||||
}
|
||||
|
||||
void manager_status_printf(Manager *m, StatusType type, const char *status, const char *format, ...) {
|
||||
|
|
|
@ -233,7 +233,6 @@ struct Manager {
|
|||
bool dispatching_dbus_queue:1;
|
||||
|
||||
bool taint_usr:1;
|
||||
bool first_boot:1;
|
||||
|
||||
bool test_run:1;
|
||||
|
||||
|
@ -295,6 +294,8 @@ struct Manager {
|
|||
|
||||
const char *unit_log_field;
|
||||
const char *unit_log_format_string;
|
||||
|
||||
int first_boot;
|
||||
};
|
||||
|
||||
int manager_new(ManagerRunningAs running_as, bool test_run, Manager **m);
|
||||
|
|
|
@ -396,7 +396,7 @@ static bool scope_check_gc(Unit *u) {
|
|||
if (u->cgroup_path) {
|
||||
int r;
|
||||
|
||||
r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, true);
|
||||
r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path);
|
||||
if (r <= 0)
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1269,7 +1269,7 @@ static int cgroup_good(Service *s) {
|
|||
if (!UNIT(s)->cgroup_path)
|
||||
return 0;
|
||||
|
||||
r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, UNIT(s)->cgroup_path, true);
|
||||
r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, UNIT(s)->cgroup_path);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
@ -1520,18 +1520,33 @@ fail:
|
|||
service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_RESOURCES);
|
||||
}
|
||||
|
||||
static bool service_good(Service *s) {
|
||||
int main_pid_ok;
|
||||
assert(s);
|
||||
|
||||
if (s->type == SERVICE_DBUS && !s->bus_name_good)
|
||||
return false;
|
||||
|
||||
main_pid_ok = main_pid_good(s);
|
||||
if (main_pid_ok > 0) /* It's alive */
|
||||
return true;
|
||||
if (main_pid_ok == 0) /* It's dead */
|
||||
return false;
|
||||
|
||||
/* OK, we don't know anything about the main PID, maybe
|
||||
* because there is none. Let's check the control group
|
||||
* instead. */
|
||||
|
||||
return cgroup_good(s) != 0;
|
||||
}
|
||||
|
||||
static void service_enter_running(Service *s, ServiceResult f) {
|
||||
int main_pid_ok, cgroup_ok;
|
||||
assert(s);
|
||||
|
||||
if (f != SERVICE_SUCCESS)
|
||||
s->result = f;
|
||||
|
||||
main_pid_ok = main_pid_good(s);
|
||||
cgroup_ok = cgroup_good(s);
|
||||
|
||||
if ((main_pid_ok > 0 || (main_pid_ok < 0 && cgroup_ok != 0)) &&
|
||||
(s->bus_name_good || s->type != SERVICE_DBUS)) {
|
||||
if (service_good(s)) {
|
||||
|
||||
/* If there are any queued up sd_notify()
|
||||
* notifications, process them now */
|
||||
|
|
|
@ -28,27 +28,28 @@
|
|||
#include "sd-id128.h"
|
||||
#include "sd-messages.h"
|
||||
#include "set.h"
|
||||
#include "unit.h"
|
||||
#include "macro.h"
|
||||
#include "strv.h"
|
||||
#include "path-util.h"
|
||||
#include "load-fragment.h"
|
||||
#include "load-dropin.h"
|
||||
#include "log.h"
|
||||
#include "unit-name.h"
|
||||
#include "dbus-unit.h"
|
||||
#include "special.h"
|
||||
#include "cgroup-util.h"
|
||||
#include "missing.h"
|
||||
#include "mkdir.h"
|
||||
#include "fileio-label.h"
|
||||
#include "bus-common-errors.h"
|
||||
#include "dbus.h"
|
||||
#include "execute.h"
|
||||
#include "dropin.h"
|
||||
#include "formats-util.h"
|
||||
#include "process-util.h"
|
||||
#include "virt.h"
|
||||
#include "bus-common-errors.h"
|
||||
#include "bus-util.h"
|
||||
#include "dropin.h"
|
||||
#include "unit-name.h"
|
||||
#include "special.h"
|
||||
#include "unit.h"
|
||||
#include "load-fragment.h"
|
||||
#include "load-dropin.h"
|
||||
#include "dbus.h"
|
||||
#include "dbus-unit.h"
|
||||
#include "execute.h"
|
||||
|
||||
const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX] = {
|
||||
[UNIT_SERVICE] = &service_vtable,
|
||||
|
@ -2016,9 +2017,9 @@ void unit_unwatch_pid(Unit *u, pid_t pid) {
|
|||
assert(u);
|
||||
assert(pid >= 1);
|
||||
|
||||
hashmap_remove_value(u->manager->watch_pids1, LONG_TO_PTR(pid), u);
|
||||
hashmap_remove_value(u->manager->watch_pids2, LONG_TO_PTR(pid), u);
|
||||
set_remove(u->pids, LONG_TO_PTR(pid));
|
||||
(void) hashmap_remove_value(u->manager->watch_pids1, LONG_TO_PTR(pid), u);
|
||||
(void) hashmap_remove_value(u->manager->watch_pids2, LONG_TO_PTR(pid), u);
|
||||
(void) set_remove(u->pids, LONG_TO_PTR(pid));
|
||||
}
|
||||
|
||||
void unit_unwatch_all_pids(Unit *u) {
|
||||
|
@ -2440,6 +2441,9 @@ int unit_set_slice(Unit *u, Unit *slice) {
|
|||
if (u->type == UNIT_SLICE)
|
||||
return -EINVAL;
|
||||
|
||||
if (unit_active_state(u) != UNIT_INACTIVE)
|
||||
return -EBUSY;
|
||||
|
||||
if (slice->type != UNIT_SLICE)
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -3168,7 +3172,7 @@ int unit_kill_common(
|
|||
if (!pid_set)
|
||||
return -ENOMEM;
|
||||
|
||||
q = cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, signo, false, true, false, pid_set);
|
||||
q = cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, signo, false, false, false, pid_set);
|
||||
if (q < 0 && q != -EAGAIN && q != -ESRCH && q != -ENOENT)
|
||||
r = q;
|
||||
}
|
||||
|
@ -3524,7 +3528,8 @@ int unit_kill_context(
|
|||
pid_t control_pid,
|
||||
bool main_pid_alien) {
|
||||
|
||||
int sig, wait_for_exit = false, r;
|
||||
bool wait_for_exit = false;
|
||||
int sig, r;
|
||||
|
||||
assert(u);
|
||||
assert(c);
|
||||
|
@ -3553,13 +3558,13 @@ int unit_kill_context(
|
|||
_cleanup_free_ char *comm = NULL;
|
||||
get_process_comm(main_pid, &comm);
|
||||
|
||||
log_unit_warning_errno(u, r, "Failed to kill main process " PID_FMT " (%s): %m", main_pid, strna(comm));
|
||||
log_unit_warning_errno(u, r, "Failed to kill main process " PID_FMT " (%s), ignoring: %m", main_pid, strna(comm));
|
||||
} else {
|
||||
if (!main_pid_alien)
|
||||
wait_for_exit = true;
|
||||
|
||||
if (c->send_sighup && k != KILL_KILL)
|
||||
kill(main_pid, SIGHUP);
|
||||
if (c->send_sighup && k == KILL_TERMINATE)
|
||||
(void) kill(main_pid, SIGHUP);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3570,16 +3575,17 @@ int unit_kill_context(
|
|||
_cleanup_free_ char *comm = NULL;
|
||||
get_process_comm(control_pid, &comm);
|
||||
|
||||
log_unit_warning_errno(u, r, "Failed to kill control process " PID_FMT " (%s): %m", control_pid, strna(comm));
|
||||
log_unit_warning_errno(u, r, "Failed to kill control process " PID_FMT " (%s), ignoring: %m", control_pid, strna(comm));
|
||||
} else {
|
||||
wait_for_exit = true;
|
||||
|
||||
if (c->send_sighup && k != KILL_KILL)
|
||||
kill(control_pid, SIGHUP);
|
||||
if (c->send_sighup && k == KILL_TERMINATE)
|
||||
(void) kill(control_pid, SIGHUP);
|
||||
}
|
||||
}
|
||||
|
||||
if ((c->kill_mode == KILL_CONTROL_GROUP || (c->kill_mode == KILL_MIXED && k == KILL_KILL)) && u->cgroup_path) {
|
||||
if (u->cgroup_path &&
|
||||
(c->kill_mode == KILL_CONTROL_GROUP || (c->kill_mode == KILL_MIXED && k == KILL_KILL))) {
|
||||
_cleanup_set_free_ Set *pid_set = NULL;
|
||||
|
||||
/* Exclude the main/control pids from being killed via the cgroup */
|
||||
|
@ -3587,21 +3593,26 @@ int unit_kill_context(
|
|||
if (!pid_set)
|
||||
return -ENOMEM;
|
||||
|
||||
r = cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, sig, true, true, false, pid_set);
|
||||
r = cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, sig, true, k != KILL_TERMINATE, false, pid_set);
|
||||
if (r < 0) {
|
||||
if (r != -EAGAIN && r != -ESRCH && r != -ENOENT)
|
||||
log_unit_warning_errno(u, r, "Failed to kill control group: %m");
|
||||
log_unit_warning_errno(u, r, "Failed to kill control group %s, ignoring: %m", u->cgroup_path);
|
||||
|
||||
} else if (r > 0) {
|
||||
|
||||
/* FIXME: For now, we will not wait for the
|
||||
* cgroup members to die, simply because
|
||||
* cgroup notification is unreliable. It
|
||||
* doesn't work at all in containers, and
|
||||
* outside of containers it can be confused
|
||||
* easily by leaving directories in the
|
||||
* cgroup. */
|
||||
* cgroup members to die if we are running in
|
||||
* a container or if this is a delegation
|
||||
* unit, simply because cgroup notification is
|
||||
* unreliable in these cases. It doesn't work
|
||||
* at all in containers, and outside of
|
||||
* containers it can be confused easily by
|
||||
* left-over directories in the cgroup --
|
||||
* which however should not exist in
|
||||
* non-delegated units. */
|
||||
|
||||
/* wait_for_exit = true; */
|
||||
if (detect_container(NULL) == 0 && !unit_cgroup_delegate(u))
|
||||
wait_for_exit = true;
|
||||
|
||||
if (c->send_sighup && k != KILL_KILL) {
|
||||
set_free(pid_set);
|
||||
|
|
|
@ -237,11 +237,13 @@ _public_ int sd_uid_get_display(uid_t uid, char **session) {
|
|||
return r;
|
||||
|
||||
r = parse_env_file(p, NEWLINE, "DISPLAY", &s, NULL);
|
||||
if (r == -ENOENT)
|
||||
return -ENXIO;
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (isempty(s))
|
||||
return -ENOENT;
|
||||
return -ENXIO;
|
||||
|
||||
*session = s;
|
||||
s = NULL;
|
||||
|
@ -465,7 +467,7 @@ static int session_get_string(const char *session, const char *field, char **val
|
|||
return r;
|
||||
|
||||
if (isempty(s))
|
||||
return -ENOENT;
|
||||
return -ENXIO;
|
||||
|
||||
*value = s;
|
||||
s = NULL;
|
||||
|
|
|
@ -33,7 +33,7 @@ static void test_login(void) {
|
|||
_cleanup_free_ char *pp = NULL, *qq = NULL;
|
||||
int r, k;
|
||||
uid_t u, u2;
|
||||
char *seat, *type, *class, *display, *remote_user, *remote_host;
|
||||
char *seat, *type, *class, *display, *remote_user, *remote_host, *display_session;
|
||||
char *session;
|
||||
char *state;
|
||||
char *session2;
|
||||
|
@ -50,6 +50,12 @@ static void test_login(void) {
|
|||
assert_se(sd_pid_get_owner_uid(0, &u2) == 0);
|
||||
printf("user = "UID_FMT"\n", u2);
|
||||
|
||||
display_session = NULL;
|
||||
r = sd_uid_get_display(u2, &display_session);
|
||||
assert_se(r >= 0 || r == -ENXIO);
|
||||
printf("user's display session = %s\n", strna(display_session));
|
||||
free(display_session);
|
||||
|
||||
assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == 0);
|
||||
sd_peer_get_session(pair[0], &pp);
|
||||
sd_peer_get_session(pair[1], &qq);
|
||||
|
@ -100,16 +106,22 @@ static void test_login(void) {
|
|||
printf("class = %s\n", class);
|
||||
free(class);
|
||||
|
||||
assert_se(sd_session_get_display(session, &display) >= 0);
|
||||
printf("display = %s\n", display);
|
||||
display = NULL;
|
||||
r = sd_session_get_display(session, &display);
|
||||
assert_se(r >= 0 || r == -ENXIO);
|
||||
printf("display = %s\n", strna(display));
|
||||
free(display);
|
||||
|
||||
assert_se(sd_session_get_remote_user(session, &remote_user) >= 0);
|
||||
printf("remote_user = %s\n", remote_user);
|
||||
remote_user = NULL;
|
||||
r = sd_session_get_remote_user(session, &remote_user);
|
||||
assert_se(r >= 0 || r == -ENXIO);
|
||||
printf("remote_user = %s\n", strna(remote_user));
|
||||
free(remote_user);
|
||||
|
||||
assert_se(sd_session_get_remote_host(session, &remote_host) >= 0);
|
||||
printf("remote_host = %s\n", remote_host);
|
||||
remote_host = NULL;
|
||||
r = sd_session_get_remote_host(session, &remote_host);
|
||||
assert_se(r >= 0 || r == -ENXIO);
|
||||
printf("remote_host = %s\n", strna(remote_host));
|
||||
free(remote_host);
|
||||
|
||||
assert_se(sd_session_get_seat(session, &seat) >= 0);
|
||||
|
|
|
@ -263,7 +263,7 @@ static int show_unit_cgroup(sd_bus *bus, const char *interface, const char *unit
|
|||
if (isempty(cgroup))
|
||||
return 0;
|
||||
|
||||
if (cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, cgroup, false) != 0 && leader <= 0)
|
||||
if (cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, cgroup) != 0 && leader <= 0)
|
||||
return 0;
|
||||
|
||||
c = columns();
|
||||
|
|
|
@ -375,7 +375,7 @@ static int show_unit_cgroup(sd_bus *bus, const char *unit, pid_t leader) {
|
|||
if (r < 0)
|
||||
return bus_log_parse_error(r);
|
||||
|
||||
if (cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, cgroup, false) != 0 && leader <= 0)
|
||||
if (cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, cgroup) != 0 && leader <= 0)
|
||||
return 0;
|
||||
|
||||
c = columns();
|
||||
|
|
|
@ -152,7 +152,7 @@ int show_cgroup_by_path(const char *path, const char *prefix, unsigned n_columns
|
|||
if (!k)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!(flags & OUTPUT_SHOW_ALL) && cg_is_empty_recursive(NULL, k, false) > 0)
|
||||
if (!(flags & OUTPUT_SHOW_ALL) && cg_is_empty_recursive(NULL, k) > 0)
|
||||
continue;
|
||||
|
||||
if (!shown_pids) {
|
||||
|
|
|
@ -3557,7 +3557,7 @@ static void print_status_info(
|
|||
|
||||
if (i->control_group &&
|
||||
(i->main_pid > 0 || i->control_pid > 0 ||
|
||||
((arg_transport != BUS_TRANSPORT_LOCAL && arg_transport != BUS_TRANSPORT_MACHINE) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group, false) == 0))) {
|
||||
((arg_transport != BUS_TRANSPORT_LOCAL && arg_transport != BUS_TRANSPORT_MACHINE) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group) == 0))) {
|
||||
unsigned c;
|
||||
|
||||
printf(" CGroup: %s\n", i->control_group);
|
||||
|
|
|
@ -56,18 +56,18 @@ int main(int argc, char*argv[]) {
|
|||
assert_se(path_equal(path, "/sys/fs/cgroup/systemd/test-b/test-d"));
|
||||
free(path);
|
||||
|
||||
assert_se(cg_is_empty(SYSTEMD_CGROUP_CONTROLLER, "/test-a", false) > 0);
|
||||
assert_se(cg_is_empty(SYSTEMD_CGROUP_CONTROLLER, "/test-b", false) > 0);
|
||||
assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a", false) > 0);
|
||||
assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", false) == 0);
|
||||
assert_se(cg_is_empty(SYSTEMD_CGROUP_CONTROLLER, "/test-a") > 0);
|
||||
assert_se(cg_is_empty(SYSTEMD_CGROUP_CONTROLLER, "/test-b") > 0);
|
||||
assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a") > 0);
|
||||
assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b") == 0);
|
||||
|
||||
assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a", 0, false, false, false, NULL) == 0);
|
||||
assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", 0, false, false, false, NULL) > 0);
|
||||
|
||||
assert_se(cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", SYSTEMD_CGROUP_CONTROLLER, "/test-a", false, false) > 0);
|
||||
|
||||
assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a", false) == 0);
|
||||
assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", false) > 0);
|
||||
assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a") == 0);
|
||||
assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b") > 0);
|
||||
|
||||
assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a", 0, false, false, false, NULL) > 0);
|
||||
assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", 0, false, false, false, NULL) == 0);
|
||||
|
|
Loading…
Reference in a new issue