mirror of
https://github.com/systemd/systemd.git
synced 2024-11-30 13:53:39 +08:00
cgroup: kill processes, not tasks and other cgroup changes
This commit is contained in:
parent
5509654721
commit
c6c18be35b
22
Makefile.am
22
Makefile.am
@ -483,15 +483,18 @@ systemctl_SOURCES = \
|
||||
src/systemctl.c \
|
||||
src/utmp-wtmp.c \
|
||||
src/dbus-common.c \
|
||||
src/cgroup-show.c
|
||||
src/cgroup-show.c \
|
||||
src/cgroup-util.c
|
||||
|
||||
systemctl_CFLAGS = \
|
||||
$(AM_CFLAGS) \
|
||||
$(DBUS_CFLAGS)
|
||||
$(DBUS_CFLAGS) \
|
||||
$(CGROUP_CLAGS)
|
||||
|
||||
systemctl_LDADD = \
|
||||
libsystemd-basic.la \
|
||||
$(DBUS_LIBS)
|
||||
$(DBUS_LIBS) \
|
||||
$(CGROUP_LIBS)
|
||||
|
||||
systemd_notify_SOURCES = \
|
||||
src/notify.c \
|
||||
@ -516,13 +519,16 @@ systemd_install_CFLAGS = \
|
||||
|
||||
systemd_cgls_SOURCES = \
|
||||
src/systemd-cgls.c \
|
||||
src/cgroup-show.c
|
||||
|
||||
systemd_cgls_LDADD = \
|
||||
libsystemd-basic.la
|
||||
src/cgroup-show.c \
|
||||
src/cgroup-util.c
|
||||
|
||||
systemd_cgls_CFLAGS = \
|
||||
$(AM_CFLAGS)
|
||||
$(AM_CFLAGS) \
|
||||
$(CGROUP_CLAGS)
|
||||
|
||||
systemd_cgls_LDADD = \
|
||||
libsystemd-basic.la \
|
||||
$(CGROUP_LIBS)
|
||||
|
||||
systemadm_SOURCES = \
|
||||
src/systemadm.vala \
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
#include "util.h"
|
||||
#include "macro.h"
|
||||
#include "cgroup-util.h"
|
||||
#include "cgroup-show.h"
|
||||
|
||||
static int compare(const void *a, const void *b) {
|
||||
@ -40,8 +41,11 @@ static int compare(const void *a, const void *b) {
|
||||
|
||||
static char *get_cgroup_path(const char *name) {
|
||||
|
||||
if (startswith(name, "name=systemd:"))
|
||||
name += 13;
|
||||
if (!name)
|
||||
return strdup("/cgroup/systemd");
|
||||
|
||||
if (startswith(name, SYSTEMD_CGROUP_CONTROLLER ":"))
|
||||
name += sizeof(SYSTEMD_CGROUP_CONTROLLER);
|
||||
|
||||
if (path_startswith(name, "/cgroup"))
|
||||
return strdup(name);
|
||||
@ -60,14 +64,14 @@ static unsigned ilog10(unsigned long ul) {
|
||||
return n;
|
||||
}
|
||||
|
||||
static int show_cgroup_full(const char *name, const char *prefix, unsigned n_columns, bool more) {
|
||||
static int show_cgroup_full(const char *path, const char *prefix, unsigned n_columns, bool more) {
|
||||
char *fn;
|
||||
FILE *f;
|
||||
size_t n = 0, n_allocated = 0;
|
||||
pid_t *pids = NULL;
|
||||
char *p;
|
||||
pid_t pid, biggest = 0;
|
||||
int r;
|
||||
unsigned long biggest = 0;
|
||||
|
||||
if (n_columns <= 0)
|
||||
n_columns = columns();
|
||||
@ -75,7 +79,7 @@ static int show_cgroup_full(const char *name, const char *prefix, unsigned n_col
|
||||
if (!prefix)
|
||||
prefix = "";
|
||||
|
||||
if (!(p = get_cgroup_path(name)))
|
||||
if (!(p = get_cgroup_path(path)))
|
||||
return -ENOMEM;
|
||||
|
||||
r = asprintf(&fn, "%s/cgroup.procs", p);
|
||||
@ -90,14 +94,7 @@ static int show_cgroup_full(const char *name, const char *prefix, unsigned n_col
|
||||
if (!f)
|
||||
return -errno;
|
||||
|
||||
while (!feof(f)) {
|
||||
unsigned long ul;
|
||||
|
||||
if (fscanf(f, "%lu", &ul) != 1)
|
||||
break;
|
||||
|
||||
if (ul <= 0)
|
||||
continue;
|
||||
while ((r = cg_read_pid(f, &pid)) > 0) {
|
||||
|
||||
if (n >= n_allocated) {
|
||||
pid_t *npids;
|
||||
@ -113,12 +110,15 @@ static int show_cgroup_full(const char *name, const char *prefix, unsigned n_col
|
||||
}
|
||||
|
||||
assert(n < n_allocated);
|
||||
pids[n++] = (pid_t) ul;
|
||||
pids[n++] = pid;
|
||||
|
||||
if (ul > biggest)
|
||||
biggest = ul;
|
||||
if (pid > biggest)
|
||||
biggest = pid;
|
||||
}
|
||||
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
if (n > 0) {
|
||||
unsigned i, m;
|
||||
|
||||
@ -171,11 +171,11 @@ finish:
|
||||
return r;
|
||||
}
|
||||
|
||||
int show_cgroup(const char *name, const char *prefix, unsigned n_columns) {
|
||||
return show_cgroup_full(name, prefix, n_columns, false);
|
||||
int show_cgroup(const char *path, const char *prefix, unsigned n_columns) {
|
||||
return show_cgroup_full(path, prefix, n_columns, false);
|
||||
}
|
||||
|
||||
int show_cgroup_recursive(const char *name, const char *prefix, unsigned n_columns) {
|
||||
int show_cgroup_recursive(const char *path, const char *prefix, unsigned n_columns) {
|
||||
DIR *d;
|
||||
char *last = NULL;
|
||||
char *p1 = NULL, *p2 = NULL, *fn = NULL;
|
||||
@ -183,15 +183,13 @@ int show_cgroup_recursive(const char *name, const char *prefix, unsigned n_colum
|
||||
bool shown_pids = false;
|
||||
int r;
|
||||
|
||||
assert(name);
|
||||
|
||||
if (n_columns <= 0)
|
||||
n_columns = columns();
|
||||
|
||||
if (!prefix)
|
||||
prefix = "";
|
||||
|
||||
if (!(fn = get_cgroup_path(name)))
|
||||
if (!(fn = get_cgroup_path(path)))
|
||||
return -ENOMEM;
|
||||
|
||||
if (!(d = opendir(fn))) {
|
||||
@ -208,7 +206,7 @@ int show_cgroup_recursive(const char *name, const char *prefix, unsigned n_colum
|
||||
continue;
|
||||
|
||||
if (!shown_pids) {
|
||||
show_cgroup_full(name, prefix, n_columns, true);
|
||||
show_cgroup_full(path, prefix, n_columns, true);
|
||||
shown_pids = true;
|
||||
}
|
||||
|
||||
@ -227,14 +225,14 @@ int show_cgroup_recursive(const char *name, const char *prefix, unsigned n_colum
|
||||
last = NULL;
|
||||
}
|
||||
|
||||
if (asprintf(&last, "%s/%s", name, de->d_name) < 0) {
|
||||
if (asprintf(&last, "%s/%s", strempty(path), de->d_name) < 0) {
|
||||
r = -ENOMEM;
|
||||
goto finish;
|
||||
}
|
||||
}
|
||||
|
||||
if (!shown_pids)
|
||||
show_cgroup_full(name, prefix, n_columns, !!last);
|
||||
show_cgroup_full(path, prefix, n_columns, !!last);
|
||||
|
||||
if (last) {
|
||||
printf("%s\342\224\224 %s\n", prefix, file_name_from_path(last));
|
||||
|
@ -22,7 +22,7 @@
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
int show_cgroup(const char *name, const char *prefix, unsigned columns);
|
||||
int show_cgroup_recursive(const char *name, const char *prefix, unsigned columns);
|
||||
int show_cgroup(const char *path, const char *prefix, unsigned columns);
|
||||
int show_cgroup_recursive(const char *path, const char *prefix, unsigned columns);
|
||||
|
||||
#endif
|
||||
|
@ -33,6 +33,15 @@
|
||||
#include "macro.h"
|
||||
#include "util.h"
|
||||
|
||||
/*
|
||||
Currently, the only remaining functionality from libcgroup we call
|
||||
here is:
|
||||
|
||||
- cgroup_get_subsys_mount_point()
|
||||
- cgroup_walk_tree_begin()/cgroup_walk_tree_next()
|
||||
- cgroup_delete_cgroup_ext()
|
||||
*/
|
||||
|
||||
int cg_translate_error(int error, int _errno) {
|
||||
|
||||
switch (error) {
|
||||
@ -73,11 +82,78 @@ static struct cgroup* cg_new(const char *controller, const char *path) {
|
||||
return cgroup;
|
||||
}
|
||||
|
||||
int cg_enumerate_processes(const char *controller, const char *path, FILE **_f) {
|
||||
char *fs;
|
||||
int r;
|
||||
FILE *f;
|
||||
|
||||
assert(controller);
|
||||
assert(path);
|
||||
assert(_f);
|
||||
|
||||
if ((r = cg_get_path(controller, path, "cgroup.procs", &fs)) < 0)
|
||||
return r;
|
||||
|
||||
f = fopen(fs, "re");
|
||||
free(fs);
|
||||
|
||||
if (!f)
|
||||
return -errno;
|
||||
|
||||
*_f = f;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cg_enumerate_tasks(const char *controller, const char *path, FILE **_f) {
|
||||
char *fs;
|
||||
int r;
|
||||
FILE *f;
|
||||
|
||||
assert(controller);
|
||||
assert(path);
|
||||
assert(_f);
|
||||
|
||||
if ((r = cg_get_path(controller, path, "tasks", &fs)) < 0)
|
||||
return r;
|
||||
|
||||
f = fopen(fs, "re");
|
||||
free(fs);
|
||||
|
||||
if (!f)
|
||||
return -errno;
|
||||
|
||||
*_f = f;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cg_read_pid(FILE *f, pid_t *_pid) {
|
||||
unsigned long ul;
|
||||
|
||||
/* Note that the cgroup.procs might contain duplicates! See
|
||||
* cgroups.txt for details. */
|
||||
|
||||
errno = 0;
|
||||
if (fscanf(f, "%lu", &ul) != 1) {
|
||||
|
||||
if (feof(f))
|
||||
return 0;
|
||||
|
||||
return errno ? -errno : -EIO;
|
||||
}
|
||||
|
||||
if (ul <= 0)
|
||||
return -EIO;
|
||||
|
||||
*_pid = (pid_t) ul;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int cg_kill(const char *controller, const char *path, int sig, bool ignore_self) {
|
||||
bool killed = false, done = false;
|
||||
Set *s;
|
||||
pid_t my_pid;
|
||||
int r, ret = 0;
|
||||
FILE *f = NULL;
|
||||
|
||||
assert(controller);
|
||||
assert(path);
|
||||
@ -93,23 +169,22 @@ int cg_kill(const char *controller, const char *path, int sig, bool ignore_self)
|
||||
my_pid = getpid();
|
||||
|
||||
do {
|
||||
void *iterator = NULL;
|
||||
pid_t pid = 0;
|
||||
|
||||
pid_t pid;
|
||||
done = true;
|
||||
|
||||
r = cgroup_get_task_begin(path, controller, &iterator, &pid);
|
||||
while (r == 0) {
|
||||
if ((r = cg_enumerate_processes(controller, path, &f)) < 0)
|
||||
goto finish;
|
||||
|
||||
while ((r = cg_read_pid(f, &pid)) > 0) {
|
||||
|
||||
if (pid == my_pid && ignore_self)
|
||||
goto next;
|
||||
continue;
|
||||
|
||||
if (set_get(s, INT_TO_PTR(pid)) == INT_TO_PTR(pid))
|
||||
goto next;
|
||||
if (set_get(s, LONG_TO_PTR(pid)) == LONG_TO_PTR(pid))
|
||||
continue;
|
||||
|
||||
/* If we haven't killed this process yet, kill
|
||||
* it */
|
||||
|
||||
if (kill(pid, sig) < 0 && errno != ESRCH) {
|
||||
if (ret == 0)
|
||||
ret = -errno;
|
||||
@ -118,22 +193,12 @@ int cg_kill(const char *controller, const char *path, int sig, bool ignore_self)
|
||||
killed = true;
|
||||
done = false;
|
||||
|
||||
if ((r = set_put(s, INT_TO_PTR(pid))) < 0)
|
||||
goto loop_exit;
|
||||
|
||||
next:
|
||||
r = cgroup_get_task_next(&iterator, &pid);
|
||||
if ((r = set_put(s, LONG_TO_PTR(pid))) < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (r == 0 || r == ECGEOF)
|
||||
r = 0;
|
||||
else if (r == ECGOTHER && errno == ENOENT)
|
||||
r = -ESRCH;
|
||||
else
|
||||
r = cg_translate_error(r, errno);
|
||||
|
||||
loop_exit:
|
||||
assert_se(cgroup_get_task_end(&iterator) == 0);
|
||||
fclose(f);
|
||||
f = NULL;
|
||||
|
||||
/* To avoid racing against processes which fork
|
||||
* quicker than we can kill them we repeat this until
|
||||
@ -141,14 +206,18 @@ int cg_kill(const char *controller, const char *path, int sig, bool ignore_self)
|
||||
|
||||
} while (!done && r >= 0);
|
||||
|
||||
finish:
|
||||
set_free(s);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (f)
|
||||
fclose(f);
|
||||
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return !!killed;
|
||||
}
|
||||
|
||||
@ -237,63 +306,53 @@ int cg_kill_recursive_and_wait(const char *controller, const char *path) {
|
||||
|
||||
int cg_migrate(const char *controller, const char *from, const char *to, bool ignore_self) {
|
||||
bool migrated = false, done = false;
|
||||
struct cgroup *dest;
|
||||
int r, ret = 0;
|
||||
pid_t my_pid;
|
||||
FILE *f = NULL;
|
||||
|
||||
assert(controller);
|
||||
assert(from);
|
||||
assert(to);
|
||||
|
||||
if (!(dest = cg_new(controller, to)))
|
||||
return -ENOMEM;
|
||||
|
||||
my_pid = getpid();
|
||||
|
||||
do {
|
||||
void *iterator = NULL;
|
||||
pid_t pid = 0;
|
||||
|
||||
pid_t pid;
|
||||
done = true;
|
||||
|
||||
r = cgroup_get_task_begin(from, controller, &iterator, &pid);
|
||||
while (r == 0) {
|
||||
if ((r = cg_enumerate_tasks(controller, from, &f)) < 0)
|
||||
goto finish;
|
||||
|
||||
while ((r = cg_read_pid(f, &pid)) > 0) {
|
||||
|
||||
if (pid == my_pid && ignore_self)
|
||||
goto next;
|
||||
continue;
|
||||
|
||||
if ((r = cgroup_attach_task_pid(dest, pid)) != 0) {
|
||||
if ((r = cg_attach(controller, to, pid)) < 0) {
|
||||
if (ret == 0)
|
||||
r = cg_translate_error(r, errno);
|
||||
ret = -r;
|
||||
}
|
||||
|
||||
migrated = true;
|
||||
done = false;
|
||||
|
||||
next:
|
||||
|
||||
r = cgroup_get_task_next(&iterator, &pid);
|
||||
}
|
||||
|
||||
if (r == 0 || r == ECGEOF)
|
||||
r = 0;
|
||||
else if (r == ECGOTHER && errno == ENOENT)
|
||||
r = -ESRCH;
|
||||
else
|
||||
r = cg_translate_error(r, errno);
|
||||
|
||||
assert_se(cgroup_get_task_end(&iterator) == 0);
|
||||
fclose(f);
|
||||
f = NULL;
|
||||
|
||||
} while (!done && r >= 0);
|
||||
|
||||
cgroup_free(&dest);
|
||||
finish:
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (f)
|
||||
fclose(f);
|
||||
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return !!migrated;
|
||||
}
|
||||
|
||||
@ -354,18 +413,24 @@ int cg_get_path(const char *controller, const char *path, const char *suffix, ch
|
||||
int r;
|
||||
|
||||
assert(controller);
|
||||
assert(path);
|
||||
|
||||
if ((r = cgroup_get_subsys_mount_point(controller, &mp)) != 0)
|
||||
return cg_translate_error(r, errno);
|
||||
|
||||
if (suffix)
|
||||
if (path && suffix)
|
||||
r = asprintf(fs, "%s/%s/%s", mp, path, suffix);
|
||||
else
|
||||
else if (path)
|
||||
r = asprintf(fs, "%s/%s", mp, path);
|
||||
else if (suffix)
|
||||
r = asprintf(fs, "%s/%s", mp, suffix);
|
||||
else {
|
||||
path_kill_slashes(mp);
|
||||
*fs = mp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
free(mp);
|
||||
|
||||
path_kill_slashes(*fs);
|
||||
return r < 0 ? -ENOMEM : 0;
|
||||
}
|
||||
|
||||
@ -409,83 +474,59 @@ finish:
|
||||
}
|
||||
|
||||
int cg_create(const char *controller, const char *path) {
|
||||
struct cgroup *cg;
|
||||
char *fs;
|
||||
int r;
|
||||
|
||||
assert(controller);
|
||||
assert(path);
|
||||
|
||||
if (!(cg = cg_new(controller, path)))
|
||||
return -ENOMEM;
|
||||
if ((r = cg_get_path(controller, path, NULL, &fs)) < 0)
|
||||
return r;
|
||||
|
||||
if ((r = cgroup_create_cgroup(cg, 1)) != 0) {
|
||||
r = cg_translate_error(r, errno);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
r = 0;
|
||||
|
||||
finish:
|
||||
cgroup_free(&cg);
|
||||
r = mkdir_p(fs, 0755);
|
||||
free(fs);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int cg_attach(const char *controller, const char *path, pid_t pid) {
|
||||
struct cgroup *cg;
|
||||
char *fs;
|
||||
int r;
|
||||
char c[32];
|
||||
|
||||
assert(controller);
|
||||
assert(path);
|
||||
assert(pid >= 0);
|
||||
|
||||
if (!(cg = cg_new(controller, path)))
|
||||
return -ENOMEM;
|
||||
if ((r = cg_get_path(controller, path, "tasks", &fs)) < 0)
|
||||
return r;
|
||||
|
||||
if (pid == 0)
|
||||
pid = getpid();
|
||||
|
||||
if ((r = cgroup_attach_task_pid(cg, pid))) {
|
||||
r = cg_translate_error(r, errno);
|
||||
goto finish;
|
||||
}
|
||||
snprintf(c, sizeof(c), "%lu\n", (unsigned long) pid);
|
||||
char_array_0(c);
|
||||
|
||||
r = 0;
|
||||
|
||||
finish:
|
||||
cgroup_free(&cg);
|
||||
r = write_one_line_file(fs, c);
|
||||
free(fs);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int cg_create_and_attach(const char *controller, const char *path, pid_t pid) {
|
||||
struct cgroup *cg;
|
||||
int r;
|
||||
|
||||
assert(controller);
|
||||
assert(path);
|
||||
assert(pid >= 0);
|
||||
|
||||
if (!(cg = cg_new(controller, path)))
|
||||
return -ENOMEM;
|
||||
if ((r = cg_create(controller, path)) < 0)
|
||||
return r;
|
||||
|
||||
if ((r = cgroup_create_cgroup(cg, 1)) != 0) {
|
||||
r = cg_translate_error(r, errno);
|
||||
goto finish;
|
||||
}
|
||||
if ((r = cg_attach(controller, path, pid)) < 0)
|
||||
return r;
|
||||
|
||||
if (pid == 0)
|
||||
pid = getpid();
|
||||
|
||||
if ((r = cgroup_attach_task_pid(cg, pid))) {
|
||||
r = cg_translate_error(r, errno);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
r = 0;
|
||||
|
||||
finish:
|
||||
cgroup_free(&cg);
|
||||
/* This does not remove the cgroup on failure */
|
||||
|
||||
return r;
|
||||
}
|
||||
@ -525,40 +566,82 @@ int cg_set_task_access(const char *controller, const char *path, mode_t mode, ui
|
||||
int cg_get_by_pid(const char *controller, pid_t pid, char **path) {
|
||||
int r;
|
||||
char *p = NULL;
|
||||
FILE *f;
|
||||
char *fs;
|
||||
size_t cs;
|
||||
|
||||
assert(controller);
|
||||
assert(pid > 0);
|
||||
assert(path);
|
||||
assert(pid >= 0);
|
||||
|
||||
if ((r = cgroup_get_current_controller_path(pid, controller, &p)) != 0)
|
||||
return cg_translate_error(r, errno);
|
||||
if (pid == 0)
|
||||
pid = getpid();
|
||||
|
||||
assert(p);
|
||||
if (asprintf(&fs, "/proc/%lu/cgroup", (unsigned long) pid) < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
*path = p;
|
||||
return 0;
|
||||
f = fopen(fs, "re");
|
||||
free(fs);
|
||||
|
||||
cs = strlen(controller);
|
||||
|
||||
while (!feof(f)) {
|
||||
char line[LINE_MAX];
|
||||
char *l;
|
||||
|
||||
errno = 0;
|
||||
if (!(fgets(line, sizeof(line), f))) {
|
||||
if (feof(f))
|
||||
break;
|
||||
|
||||
r = errno ? -errno : -EIO;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
truncate_nl(line);
|
||||
|
||||
if (!(l = strchr(line, ':')))
|
||||
continue;
|
||||
|
||||
l++;
|
||||
if (strncmp(l, controller, cs) != 0)
|
||||
continue;
|
||||
|
||||
if (l[cs] != ':')
|
||||
continue;
|
||||
|
||||
if (!(p = strdup(l + cs + 1))) {
|
||||
r = -ENOMEM;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
*path = p;
|
||||
r = 0;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
r = -ENOENT;
|
||||
|
||||
finish:
|
||||
fclose(f);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int cg_install_release_agent(const char *controller, const char *agent) {
|
||||
char *mp = NULL, *path = NULL, *contents = NULL, *line = NULL, *sc;
|
||||
char *fs = NULL, *contents = NULL, *line = NULL, *sc;
|
||||
int r;
|
||||
|
||||
assert(controller);
|
||||
assert(agent);
|
||||
|
||||
if ((r = cgroup_get_subsys_mount_point(controller, &mp)) != 0)
|
||||
return cg_translate_error(r, errno);
|
||||
if ((r = cg_get_path(controller, NULL, "release_agent", &fs)) < 0)
|
||||
return r;
|
||||
|
||||
if (asprintf(&path, "%s/release_agent", mp) < 0) {
|
||||
r = -ENOMEM;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if ((r = read_one_line_file(path, &contents)) < 0)
|
||||
if ((r = read_one_line_file(fs, &contents)) < 0)
|
||||
goto finish;
|
||||
|
||||
sc = strstrip(contents);
|
||||
|
||||
if (sc[0] == 0) {
|
||||
|
||||
if (asprintf(&line, "%s\n", agent) < 0) {
|
||||
@ -566,7 +649,7 @@ int cg_install_release_agent(const char *controller, const char *agent) {
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if ((r = write_one_line_file(path, line)) < 0)
|
||||
if ((r = write_one_line_file(fs, line)) < 0)
|
||||
goto finish;
|
||||
|
||||
} else if (!streq(sc, agent)) {
|
||||
@ -574,33 +657,33 @@ int cg_install_release_agent(const char *controller, const char *agent) {
|
||||
goto finish;
|
||||
}
|
||||
|
||||
free(path);
|
||||
path = NULL;
|
||||
if (asprintf(&path, "%s/notify_on_release", mp) < 0) {
|
||||
free(fs);
|
||||
fs = NULL;
|
||||
if ((r = cg_get_path(controller, NULL, "notify_on_release", &fs)) < 0) {
|
||||
r = -ENOMEM;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
free(contents);
|
||||
contents = NULL;
|
||||
if ((r = read_one_line_file(path, &contents)) < 0)
|
||||
if ((r = read_one_line_file(fs, &contents)) < 0)
|
||||
goto finish;
|
||||
|
||||
sc = strstrip(contents);
|
||||
|
||||
if (streq(sc, "0")) {
|
||||
if ((r = write_one_line_file(path, "1\n")) < 0)
|
||||
if ((r = write_one_line_file(fs, "1\n")) < 0)
|
||||
goto finish;
|
||||
|
||||
r = 1;
|
||||
} else if (!streq(sc, "1")) {
|
||||
r = -EIO;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
r = 0;
|
||||
} else
|
||||
r = 0;
|
||||
|
||||
finish:
|
||||
free(mp);
|
||||
free(path);
|
||||
free(fs);
|
||||
free(contents);
|
||||
free(line);
|
||||
|
||||
@ -608,36 +691,32 @@ finish:
|
||||
}
|
||||
|
||||
int cg_is_empty(const char *controller, const char *path, bool ignore_self) {
|
||||
void *iterator = NULL;
|
||||
pid_t pid = 0;
|
||||
pid_t pid;
|
||||
int r;
|
||||
FILE *f;
|
||||
bool found = false;
|
||||
|
||||
assert(controller);
|
||||
assert(path);
|
||||
|
||||
r = cgroup_get_task_begin(path, controller, &iterator, &pid);
|
||||
while (r == 0) {
|
||||
if ((r = cg_enumerate_tasks(controller, path, &f)) < 0)
|
||||
return r;
|
||||
|
||||
if (ignore_self&& pid == getpid())
|
||||
goto next;
|
||||
while ((r = cg_read_pid(f, &pid)) > 0) {
|
||||
|
||||
if (ignore_self && pid == getpid())
|
||||
continue;
|
||||
|
||||
found = true;
|
||||
break;
|
||||
|
||||
next:
|
||||
r = cgroup_get_task_next(&iterator, &pid);
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
if (r == ECGEOF)
|
||||
r = 1;
|
||||
else if (r != 0)
|
||||
r = cg_translate_error(r, errno);
|
||||
else
|
||||
r = 0;
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
assert_se(cgroup_get_task_end(&iterator) == 0);
|
||||
|
||||
return r;
|
||||
return !found;
|
||||
}
|
||||
|
||||
int cg_is_empty_recursive(const char *controller, const char *path, bool ignore_self) {
|
||||
@ -692,3 +771,12 @@ int cg_is_empty_recursive(const char *controller, const char *path, bool ignore_
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cg_init(void) {
|
||||
int r;
|
||||
|
||||
if ((r = cgroup_init()) != 0)
|
||||
return cg_translate_error(r, errno);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -23,9 +23,19 @@
|
||||
***/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "set.h"
|
||||
|
||||
#define SYSTEMD_CGROUP_CONTROLLER "name=systemd"
|
||||
|
||||
int cg_translate_error(int error, int _errno);
|
||||
|
||||
int cg_enumerate_processes(const char *controller, const char *path, FILE **_f);
|
||||
int cg_enumerate_tasks(const char *controller, const char *path, FILE **_f);
|
||||
|
||||
int cg_read_pid(FILE *f, pid_t *_pid);
|
||||
|
||||
int cg_kill(const char *controller, const char *path, int sig, bool ignore_self);
|
||||
int cg_kill_recursive(const char *controller, const char *path, int sig, bool ignore_self);
|
||||
int cg_kill_recursive_and_wait(const char *controller, const char *path);
|
||||
@ -51,4 +61,6 @@ int cg_install_release_agent(const char *controller, const char *agent);
|
||||
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_init(void);
|
||||
|
||||
#endif
|
||||
|
95
src/cgroup.c
95
src/cgroup.c
@ -25,8 +25,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
#include <sys/mount.h>
|
||||
|
||||
#include <libcgroup.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "cgroup.h"
|
||||
#include "cgroup-util.h"
|
||||
@ -210,71 +209,91 @@ int cgroup_bonding_is_empty_list(CGroupBonding *first) {
|
||||
}
|
||||
|
||||
int manager_setup_cgroup(Manager *m) {
|
||||
char *cp;
|
||||
char *current = NULL, *path = NULL;
|
||||
int r;
|
||||
pid_t pid;
|
||||
char suffix[32];
|
||||
|
||||
assert(m);
|
||||
|
||||
if ((r = cgroup_init()) != 0) {
|
||||
log_error("Failed to initialize libcg: %s", cgroup_strerror(r));
|
||||
return cg_translate_error(r, errno);
|
||||
/* 1. Initialize libcg */
|
||||
if ((r = cg_init()) < 0) {
|
||||
log_error("Failed to initialize libcg: %s", strerror(-r));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
free(m->cgroup_mount_point);
|
||||
m->cgroup_mount_point = NULL;
|
||||
if ((r = cgroup_get_subsys_mount_point(SYSTEMD_CGROUP_CONTROLLER, &m->cgroup_mount_point)))
|
||||
return cg_translate_error(r, errno);
|
||||
/* 2. Determine hierarchy */
|
||||
if ((r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, 0, ¤t)) < 0)
|
||||
goto finish;
|
||||
|
||||
pid = getpid();
|
||||
|
||||
if ((r = cgroup_get_current_controller_path(pid, SYSTEMD_CGROUP_CONTROLLER, &cp)))
|
||||
return cg_translate_error(r, errno);
|
||||
|
||||
snprintf(suffix, sizeof(suffix), "/systemd-%u", (unsigned) pid);
|
||||
snprintf(suffix, sizeof(suffix), "/systemd-%lu", (unsigned long) getpid());
|
||||
char_array_0(suffix);
|
||||
|
||||
free(m->cgroup_hierarchy);
|
||||
|
||||
if (endswith(cp, suffix))
|
||||
if (endswith(current, suffix)) {
|
||||
/* We probably got reexecuted and can continue to use our root cgroup */
|
||||
m->cgroup_hierarchy = cp;
|
||||
else {
|
||||
m->cgroup_hierarchy = current;
|
||||
current = NULL;
|
||||
|
||||
} else {
|
||||
/* We need a new root cgroup */
|
||||
|
||||
m->cgroup_hierarchy = NULL;
|
||||
r = asprintf(&m->cgroup_hierarchy, "%s%s", streq(cp, "/") ? "" : cp, suffix);
|
||||
free(cp);
|
||||
|
||||
if (r < 0)
|
||||
return -ENOMEM;
|
||||
if ((r = asprintf(&m->cgroup_hierarchy, "%s%s", streq(current, "/") ? "" : current, suffix)) < 0) {
|
||||
r = -ENOMEM;
|
||||
goto finish;
|
||||
}
|
||||
}
|
||||
|
||||
log_debug("Using cgroup controller <" SYSTEMD_CGROUP_CONTROLLER ">, hierarchy mounted at <%s>, using root group <%s>.",
|
||||
m->cgroup_mount_point,
|
||||
m->cgroup_hierarchy);
|
||||
/* 3. Show data */
|
||||
if ((r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_hierarchy, NULL, &path)) < 0)
|
||||
goto finish;
|
||||
|
||||
log_debug("Using cgroup controller " SYSTEMD_CGROUP_CONTROLLER ". File system hierarchy is at %s.", path);
|
||||
|
||||
/* 4. Install agent */
|
||||
if ((r = cg_install_release_agent(SYSTEMD_CGROUP_CONTROLLER, CGROUP_AGENT_PATH)) < 0)
|
||||
log_warning("Failed to install release agent, ignoring: %s", strerror(-r));
|
||||
else if (r > 0)
|
||||
log_debug("Installed release agent.");
|
||||
else
|
||||
log_debug("Installed release agent, or already installed.");
|
||||
log_debug("Release agent already installed.");
|
||||
|
||||
if ((r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_hierarchy, 0)) < 0)
|
||||
/* 5. Realize the group */
|
||||
if ((r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_hierarchy, 0)) < 0) {
|
||||
log_error("Failed to create root cgroup hierarchy: %s", strerror(-r));
|
||||
else
|
||||
log_debug("Created root group.");
|
||||
goto finish;
|
||||
}
|
||||
|
||||
/* 6. And pin it, so that it cannot be unmounted */
|
||||
if (m->pin_cgroupfs_fd >= 0)
|
||||
close_nointr_nofail(m->pin_cgroupfs_fd);
|
||||
|
||||
if ((m->pin_cgroupfs_fd = open(path, O_RDONLY|O_CLOEXEC|O_DIRECTORY|O_NOCTTY|O_NONBLOCK)) < 0) {
|
||||
r = -errno;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
log_debug("Created root group.");
|
||||
|
||||
finish:
|
||||
free(current);
|
||||
free(path);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int manager_shutdown_cgroup(Manager *m) {
|
||||
void manager_shutdown_cgroup(Manager *m, bool delete) {
|
||||
assert(m);
|
||||
|
||||
if (!m->cgroup_hierarchy)
|
||||
return 0;
|
||||
if (delete && m->cgroup_hierarchy)
|
||||
cg_delete(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_hierarchy);
|
||||
|
||||
return cg_delete(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_hierarchy);
|
||||
if (m->pin_cgroupfs_fd >= 0) {
|
||||
close_nointr_nofail(m->pin_cgroupfs_fd);
|
||||
m->pin_cgroupfs_fd = -1;
|
||||
}
|
||||
|
||||
free(m->cgroup_hierarchy);
|
||||
m->cgroup_hierarchy = NULL;
|
||||
}
|
||||
|
||||
int cgroup_notify_empty(Manager *m, const char *group) {
|
||||
|
@ -26,8 +26,6 @@ typedef struct CGroupBonding CGroupBonding;
|
||||
|
||||
#include "unit.h"
|
||||
|
||||
#define SYSTEMD_CGROUP_CONTROLLER "name=systemd"
|
||||
|
||||
/* Binds a cgroup to a name */
|
||||
struct CGroupBonding {
|
||||
char *controller;
|
||||
@ -76,7 +74,7 @@ char *cgroup_bonding_to_string(CGroupBonding *b);
|
||||
#include "manager.h"
|
||||
|
||||
int manager_setup_cgroup(Manager *m);
|
||||
int manager_shutdown_cgroup(Manager *m);
|
||||
void manager_shutdown_cgroup(Manager *m, bool delete);
|
||||
|
||||
int cgroup_notify_empty(Manager *m, const char *group);
|
||||
|
||||
|
@ -121,6 +121,7 @@
|
||||
" <property name=\"SysVInitPath\" type=\"as\" access=\"read\"/>\n" \
|
||||
" <property name=\"SysVRcndPath\" type=\"as\" access=\"read\"/>\n" \
|
||||
" <property name=\"NotifySocket\" type=\"s\" access=\"read\"/>\n" \
|
||||
" <property name=\"ControlGroupHierarchy\" type=\"s\" access=\"read\"/>\n" \
|
||||
" </interface>\n"
|
||||
|
||||
#define INTROSPECTION_BEGIN \
|
||||
@ -229,6 +230,7 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
|
||||
{ "org.freedesktop.systemd1.Manager", "SysVInitPath", bus_property_append_strv, "as", m->lookup_paths.sysvinit_path },
|
||||
{ "org.freedesktop.systemd1.Manager", "SysVRcndPath", bus_property_append_strv, "as", m->lookup_paths.sysvrcnd_path },
|
||||
{ "org.freedesktop.systemd1.Manager", "NotifySocket", bus_property_append_string, "s", m->notify_socket },
|
||||
{ "org.freedesktop.systemd1.Manager", "ControlGroupHierarchy", bus_property_append_string, "s", m->cgroup_hierarchy },
|
||||
{ NULL, NULL, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
|
@ -108,12 +108,18 @@ static inline size_t ALIGN(size_t l) {
|
||||
#define PTR_TO_UINT32(p) ((uint32_t) ((uintptr_t) (p)))
|
||||
#define UINT32_TO_PTR(u) ((void*) ((uintptr_t) (u)))
|
||||
|
||||
#define PTR_TO_ULONG(p) ((unsigned long) ((uintptr_t) (p)))
|
||||
#define ULONG_TO_PTR(u) ((void*) ((uintptr_t) (u)))
|
||||
|
||||
#define PTR_TO_INT(p) ((int) ((intptr_t) (p)))
|
||||
#define INT_TO_PTR(u) ((void*) ((intptr_t) (u)))
|
||||
|
||||
#define TO_INT32(p) ((int32_t) ((intptr_t) (p)))
|
||||
#define INT32_TO_PTR(u) ((void*) ((intptr_t) (u)))
|
||||
|
||||
#define PTR_TO_LONG(p) ((long) ((intptr_t) (p)))
|
||||
#define LONG_TO_PTR(u) ((void*) ((intptr_t) (u)))
|
||||
|
||||
#define memzero(x,l) (memset((x), 0, (l)))
|
||||
#define zero(x) (memzero(&(x), sizeof(x)))
|
||||
|
||||
|
@ -186,7 +186,6 @@ static int manager_setup_signals(Manager *m) {
|
||||
int manager_new(ManagerRunningAs running_as, Manager **_m) {
|
||||
Manager *m;
|
||||
int r = -ENOMEM;
|
||||
char *p;
|
||||
|
||||
assert(_m);
|
||||
assert(running_as >= 0);
|
||||
@ -245,14 +244,6 @@ int manager_new(ManagerRunningAs running_as, Manager **_m) {
|
||||
if ((r = bus_init(m)) < 0)
|
||||
goto fail;
|
||||
|
||||
if (asprintf(&p, "%s/%s", m->cgroup_mount_point, m->cgroup_hierarchy) < 0) {
|
||||
r = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
m->pin_cgroupfs_fd = open(p, O_RDONLY|O_CLOEXEC|O_DIRECTORY|O_NOCTTY|O_NONBLOCK);
|
||||
free(p);
|
||||
|
||||
*_m = m;
|
||||
return 0;
|
||||
|
||||
@ -420,8 +411,7 @@ void manager_free(Manager *m) {
|
||||
|
||||
/* If we reexecute ourselves, we keep the root cgroup
|
||||
* around */
|
||||
if (m->exit_code != MANAGER_REEXECUTE)
|
||||
manager_shutdown_cgroup(m);
|
||||
manager_shutdown_cgroup(m, m->exit_code != MANAGER_REEXECUTE);
|
||||
|
||||
bus_done(m);
|
||||
|
||||
@ -443,13 +433,8 @@ void manager_free(Manager *m) {
|
||||
lookup_paths_free(&m->lookup_paths);
|
||||
strv_free(m->environment);
|
||||
|
||||
free(m->cgroup_hierarchy);
|
||||
free(m->cgroup_mount_point);
|
||||
|
||||
hashmap_free(m->cgroup_bondings);
|
||||
|
||||
if (m->pin_cgroupfs_fd >= 0)
|
||||
close_nointr_nofail(m->pin_cgroupfs_fd);
|
||||
set_free_free(m->unit_path_cache);
|
||||
|
||||
free(m);
|
||||
}
|
||||
@ -1664,7 +1649,7 @@ static int manager_process_notify_fd(Manager *m) {
|
||||
|
||||
ucred = (struct ucred*) CMSG_DATA(&control.cmsghdr);
|
||||
|
||||
if (!(u = hashmap_get(m->watch_pids, UINT32_TO_PTR(ucred->pid))))
|
||||
if (!(u = hashmap_get(m->watch_pids, LONG_TO_PTR(ucred->pid))))
|
||||
if (!(u = cgroup_unit_by_pid(m, ucred->pid))) {
|
||||
log_warning("Cannot find unit for notify message of PID %lu.", (unsigned long) ucred->pid);
|
||||
continue;
|
||||
@ -1729,7 +1714,7 @@ static int manager_dispatch_sigchld(Manager *m) {
|
||||
return r;
|
||||
|
||||
/* And now figure out the unit this belongs to */
|
||||
if (!(u = hashmap_get(m->watch_pids, UINT32_TO_PTR(si.si_pid))))
|
||||
if (!(u = hashmap_get(m->watch_pids, LONG_TO_PTR(si.si_pid))))
|
||||
u = cgroup_unit_by_pid(m, si.si_pid);
|
||||
|
||||
/* And now, we actually reap the zombie. */
|
||||
@ -1752,9 +1737,9 @@ static int manager_dispatch_sigchld(Manager *m) {
|
||||
if (!u)
|
||||
continue;
|
||||
|
||||
log_debug("Child %llu belongs to %s", (long long unsigned) si.si_pid, u->meta.id);
|
||||
log_debug("Child %lu belongs to %s", (long unsigned) si.si_pid, u->meta.id);
|
||||
|
||||
hashmap_remove(m->watch_pids, UINT32_TO_PTR(si.si_pid));
|
||||
hashmap_remove(m->watch_pids, LONG_TO_PTR(si.si_pid));
|
||||
UNIT_VTABLE(u)->sigchld_event(u, si.si_pid, si.si_code, si.si_status);
|
||||
}
|
||||
|
||||
|
@ -171,7 +171,6 @@ struct Manager {
|
||||
|
||||
/* Data specific to the cgroup subsystem */
|
||||
Hashmap *cgroup_bondings; /* path string => CGroupBonding object 1:n */
|
||||
char *cgroup_mount_point;
|
||||
char *cgroup_hierarchy;
|
||||
|
||||
usec_t gc_queue_timestamp;
|
||||
|
@ -217,17 +217,17 @@ static int create_user_group(pam_handle_t *handle, const char *group, struct pas
|
||||
assert(group);
|
||||
|
||||
if (attach)
|
||||
r = cg_create_and_attach("name=systemd", group, 0);
|
||||
r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, group, 0);
|
||||
else
|
||||
r = cg_create("name=systemd", group);
|
||||
r = cg_create(SYSTEMD_CGROUP_CONTROLLER, group);
|
||||
|
||||
if (r < 0) {
|
||||
pam_syslog(handle, LOG_ERR, "Failed to create cgroup: %s", strerror(-r));
|
||||
return PAM_SESSION_ERR;
|
||||
}
|
||||
|
||||
if ((r = cg_set_task_access("name=systemd", group, 0755, pw->pw_uid, pw->pw_gid)) < 0 ||
|
||||
(r = cg_set_group_access("name=systemd", group, 0755, pw->pw_uid, pw->pw_gid)) < 0) {
|
||||
if ((r = cg_set_task_access(SYSTEMD_CGROUP_CONTROLLER, group, 0755, pw->pw_uid, pw->pw_gid)) < 0 ||
|
||||
(r = cg_set_group_access(SYSTEMD_CGROUP_CONTROLLER, group, 0755, pw->pw_uid, pw->pw_gid)) < 0) {
|
||||
pam_syslog(handle, LOG_ERR, "Failed to change access modes: %s", strerror(-r));
|
||||
return PAM_SESSION_ERR;
|
||||
}
|
||||
@ -258,8 +258,8 @@ _public_ PAM_EXTERN int pam_sm_open_session(
|
||||
if (sd_booted() <= 0)
|
||||
return PAM_SUCCESS;
|
||||
|
||||
if ((r = cgroup_init()) != 0) {
|
||||
pam_syslog(handle, LOG_ERR, "libcgroup initialization failed: %s", cgroup_strerror(r));
|
||||
if ((r = cg_init()) < 0) {
|
||||
pam_syslog(handle, LOG_ERR, "libcgroup initialization failed: %s", strerror(-r));
|
||||
r = PAM_SESSION_ERR;
|
||||
goto finish;
|
||||
}
|
||||
@ -361,7 +361,7 @@ static int session_remains(pam_handle_t *handle, const char *user_path) {
|
||||
|
||||
zero(info);
|
||||
|
||||
r = cgroup_walk_tree_begin("name=systemd", user_path, 0, &iterator, &info, &level);
|
||||
r = cgroup_walk_tree_begin(SYSTEMD_CGROUP_CONTROLLER, user_path, 0, &iterator, &info, &level);
|
||||
while (r == 0) {
|
||||
|
||||
if (info.type != CGROUP_FILE_TYPE_DIR)
|
||||
@ -440,7 +440,7 @@ _public_ PAM_EXTERN int pam_sm_close_session(
|
||||
|
||||
if (kill_session) {
|
||||
/* Kill processes in session cgroup */
|
||||
if ((r = cg_kill_recursive_and_wait("name=systemd", session_path)) < 0)
|
||||
if ((r = cg_kill_recursive_and_wait(SYSTEMD_CGROUP_CONTROLLER, session_path)) < 0)
|
||||
pam_syslog(handle, LOG_ERR, "Failed to kill session cgroup: %s", strerror(-r));
|
||||
|
||||
} else {
|
||||
@ -450,7 +450,7 @@ _public_ PAM_EXTERN int pam_sm_close_session(
|
||||
* yet. */
|
||||
create_user_group(handle, nosession_path, pw, 0);
|
||||
|
||||
if ((r = cg_migrate_recursive("name=systemd", session_path, nosession_path, false)) < 0)
|
||||
if ((r = cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, session_path, nosession_path, false)) < 0)
|
||||
pam_syslog(handle, LOG_ERR, "Failed to migrate session cgroup: %s", strerror(-r));
|
||||
}
|
||||
|
||||
@ -458,13 +458,13 @@ _public_ PAM_EXTERN int pam_sm_close_session(
|
||||
if (r < 0)
|
||||
pam_syslog(handle, LOG_INFO, "Couldn't empty session cgroup, not deleting.");
|
||||
else {
|
||||
if ((r = cg_delete("name=systemd", session_path)) < 0)
|
||||
if ((r = cg_delete(SYSTEMD_CGROUP_CONTROLLER, session_path)) < 0)
|
||||
pam_syslog(handle, LOG_ERR, "Failed to delete session cgroup: %s", strerror(-r));
|
||||
}
|
||||
}
|
||||
|
||||
/* GC user tree */
|
||||
cg_trim("name=systemd", user_path, false);
|
||||
cg_trim(SYSTEMD_CGROUP_CONTROLLER, user_path, false);
|
||||
|
||||
if ((r = session_remains(handle, user_path)) < 0)
|
||||
pam_syslog(handle, LOG_ERR, "Failed to determine whether a session remains: %s", strerror(-r));
|
||||
@ -473,11 +473,11 @@ _public_ PAM_EXTERN int pam_sm_close_session(
|
||||
if (kill_user && r == 0) {
|
||||
|
||||
/* Kill no-session cgroup */
|
||||
if ((r = cg_kill_recursive_and_wait("name=systemd", user_path)) < 0)
|
||||
if ((r = cg_kill_recursive_and_wait(SYSTEMD_CGROUP_CONTROLLER, user_path)) < 0)
|
||||
pam_syslog(handle, LOG_ERR, "Failed to kill user cgroup: %s", strerror(-r));
|
||||
} else {
|
||||
|
||||
if ((r = cg_is_empty_recursive("name=systemd", user_path, true)) < 0)
|
||||
if ((r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, user_path, true)) < 0)
|
||||
pam_syslog(handle, LOG_ERR, "Failed to check user cgroup: %s", strerror(-r));
|
||||
|
||||
/* If we managed to kill somebody, don't cleanup the cgroup. */
|
||||
@ -489,7 +489,7 @@ _public_ PAM_EXTERN int pam_sm_close_session(
|
||||
const char *runtime_dir;
|
||||
|
||||
/* Remove user cgroup */
|
||||
if ((r = cg_delete("name=systemd", user_path)) < 0)
|
||||
if ((r = cg_delete(SYSTEMD_CGROUP_CONTROLLER, user_path)) < 0)
|
||||
pam_syslog(handle, LOG_ERR, "Failed to delete user cgroup: %s", strerror(-r));
|
||||
|
||||
/* This will migrate us to the /user cgroup. */
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include "strv.h"
|
||||
#include "dbus-common.h"
|
||||
#include "cgroup-show.h"
|
||||
#include "cgroup-util.h"
|
||||
#include "list.h"
|
||||
|
||||
static const char *arg_type = NULL;
|
||||
@ -1053,6 +1054,7 @@ typedef struct UnitStatusInfo {
|
||||
|
||||
static void print_status_info(UnitStatusInfo *i) {
|
||||
ExecStatusInfo *p;
|
||||
int r;
|
||||
|
||||
assert(i);
|
||||
|
||||
@ -1183,7 +1185,10 @@ static void print_status_info(UnitStatusInfo *i) {
|
||||
else
|
||||
c = 0;
|
||||
|
||||
show_cgroup_recursive(i->default_control_group, "\t\t ", c);
|
||||
if ((r = cg_init()) < 0)
|
||||
log_error("Failed to initialize libcg: %s", strerror(-r));
|
||||
else
|
||||
show_cgroup_recursive(i->default_control_group, "\t\t ", c);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "cgroup-show.h"
|
||||
#include "cgroup-util.h"
|
||||
#include "log.h"
|
||||
#include "util.h"
|
||||
|
||||
@ -82,6 +83,11 @@ int main(int argc, char *argv[]) {
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (cg_init() < 0) {
|
||||
log_error("Failed to initialize libcg: %s", strerror(-r));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (optind < argc) {
|
||||
unsigned i;
|
||||
|
||||
@ -105,7 +111,7 @@ int main(int argc, char *argv[]) {
|
||||
printf("Working Directory %s:\n", p);
|
||||
r = show_cgroup_recursive(p, NULL, 0);
|
||||
} else
|
||||
r = show_cgroup_recursive("", NULL, 0);
|
||||
r = show_cgroup_recursive(NULL, NULL, 0);
|
||||
|
||||
free(p);
|
||||
}
|
||||
|
@ -22,8 +22,6 @@
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <libcgroup.h>
|
||||
|
||||
#include "cgroup-util.h"
|
||||
#include "util.h"
|
||||
#include "log.h"
|
||||
@ -31,54 +29,54 @@
|
||||
int main(int argc, char*argv[]) {
|
||||
char *path;
|
||||
|
||||
assert_se(cgroup_init() == 0);
|
||||
assert_se(cg_init() >= 0);
|
||||
|
||||
assert_se(cg_create("name=systemd", "/test-a") == 0);
|
||||
assert_se(cg_create("name=systemd", "/test-a") == 0);
|
||||
assert_se(cg_create("name=systemd", "/test-b") == 0);
|
||||
assert_se(cg_create("name=systemd", "/test-b/test-c") == 0);
|
||||
assert_se(cg_create_and_attach("name=systemd", "/test-b", 0) == 0);
|
||||
assert_se(cg_create(SYSTEMD_CGROUP_CONTROLLER, "/test-a") == 0);
|
||||
assert_se(cg_create(SYSTEMD_CGROUP_CONTROLLER, "/test-a") == 0);
|
||||
assert_se(cg_create(SYSTEMD_CGROUP_CONTROLLER, "/test-b") == 0);
|
||||
assert_se(cg_create(SYSTEMD_CGROUP_CONTROLLER, "/test-b/test-c") == 0);
|
||||
assert_se(cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, "/test-b", 0) == 0);
|
||||
|
||||
assert_se(cg_get_by_pid("name=systemd", getpid(), &path) == 0);
|
||||
assert_se(cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, getpid(), &path) == 0);
|
||||
assert_se(streq(path, "/test-b"));
|
||||
free(path);
|
||||
|
||||
assert_se(cg_attach("name=systemd", "/test-a", 0) == 0);
|
||||
assert_se(cg_attach(SYSTEMD_CGROUP_CONTROLLER, "/test-a", 0) == 0);
|
||||
|
||||
assert_se(cg_get_by_pid("name=systemd", getpid(), &path) == 0);
|
||||
assert_se(cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, getpid(), &path) == 0);
|
||||
assert_se(path_equal(path, "/test-a"));
|
||||
free(path);
|
||||
|
||||
assert_se(cg_create_and_attach("name=systemd", "/test-b/test-d", 0) == 0);
|
||||
assert_se(cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, "/test-b/test-d", 0) == 0);
|
||||
|
||||
assert_se(cg_get_by_pid("name=systemd", getpid(), &path) == 0);
|
||||
assert_se(cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, getpid(), &path) == 0);
|
||||
assert_se(path_equal(path, "/test-b/test-d"));
|
||||
free(path);
|
||||
|
||||
assert_se(cg_get_path("name=systemd", "/test-b/test-d", NULL, &path) == 0);
|
||||
assert_se(cg_get_path(SYSTEMD_CGROUP_CONTROLLER, "/test-b/test-d", NULL, &path) == 0);
|
||||
assert_se(path_equal(path, "/cgroup/systemd/test-b/test-d"));
|
||||
free(path);
|
||||
|
||||
assert_se(cg_is_empty("name=systemd", "/test-a", false) > 0);
|
||||
assert_se(cg_is_empty("name=systemd", "/test-b", false) > 0);
|
||||
assert_se(cg_is_empty_recursive("name=systemd", "/test-a", false) > 0);
|
||||
assert_se(cg_is_empty_recursive("name=systemd", "/test-b", false) == 0);
|
||||
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_kill_recursive("name=systemd", "/test-a", 0, false) == 0);
|
||||
assert_se(cg_kill_recursive("name=systemd", "/test-b", 0, false) > 0);
|
||||
assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a", 0, false) == 0);
|
||||
assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", 0, false) > 0);
|
||||
|
||||
assert_se(cg_migrate_recursive("name=systemd", "/test-b", "/test-a", false) == 0);
|
||||
assert_se(cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", "/test-a", false) == 0);
|
||||
|
||||
assert_se(cg_is_empty_recursive("name=systemd", "/test-a", false) == 0);
|
||||
assert_se(cg_is_empty_recursive("name=systemd", "/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_kill_recursive("name=systemd", "/test-a", 0, false) > 0);
|
||||
assert_se(cg_kill_recursive("name=systemd", "/test-b", 0, false) == 0);
|
||||
assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a", 0, false) > 0);
|
||||
assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", 0, false) == 0);
|
||||
|
||||
cg_trim("name=systemd", "/", false);
|
||||
cg_trim(SYSTEMD_CGROUP_CONTROLLER, "/", false);
|
||||
|
||||
assert_se(cg_delete("name=systemd", "/test-b") < 0);
|
||||
assert_se(cg_delete("name=systemd", "/test-a") == 0);
|
||||
assert_se(cg_delete(SYSTEMD_CGROUP_CONTROLLER, "/test-b") < 0);
|
||||
assert_se(cg_delete(SYSTEMD_CGROUP_CONTROLLER, "/test-a") == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "specifier.h"
|
||||
#include "dbus-unit.h"
|
||||
#include "special.h"
|
||||
#include "cgroup-util.h"
|
||||
|
||||
const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX] = {
|
||||
[UNIT_SERVICE] = &service_vtable,
|
||||
@ -1144,14 +1145,14 @@ int unit_watch_pid(Unit *u, pid_t pid) {
|
||||
/* Watch a specific PID. We only support one unit watching
|
||||
* each PID for now. */
|
||||
|
||||
return hashmap_put(u->meta.manager->watch_pids, UINT32_TO_PTR(pid), u);
|
||||
return hashmap_put(u->meta.manager->watch_pids, LONG_TO_PTR(pid), u);
|
||||
}
|
||||
|
||||
void unit_unwatch_pid(Unit *u, pid_t pid) {
|
||||
assert(u);
|
||||
assert(pid >= 1);
|
||||
|
||||
hashmap_remove_value(u->meta.manager->watch_pids, UINT32_TO_PTR(pid), u);
|
||||
hashmap_remove_value(u->meta.manager->watch_pids, LONG_TO_PTR(pid), u);
|
||||
}
|
||||
|
||||
int unit_watch_timer(Unit *u, usec_t delay, Watch *w) {
|
||||
|
@ -956,7 +956,6 @@ int mkdir_parents(const char *path, mode_t mode) {
|
||||
return -ENOMEM;
|
||||
|
||||
r = mkdir(t, mode);
|
||||
|
||||
free(t);
|
||||
|
||||
if (r < 0 && errno != EEXIST)
|
||||
@ -972,7 +971,7 @@ int mkdir_p(const char *path, mode_t mode) {
|
||||
if ((r = mkdir_parents(path, mode)) < 0)
|
||||
return r;
|
||||
|
||||
if (mkdir(path, mode) < 0)
|
||||
if (mkdir(path, mode) < 0 && errno != EEXIST)
|
||||
return -errno;
|
||||
|
||||
return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user