cgroupsv2 update (Ubuntu 22.04)
Things have moved around a bit. Compared to https://unix.stackexchange.com/a/125024/32558 now you now need:
sudo cgcreate -a $USER:$USER -g memory:myGroup -t $USER:$USER
sudo cgset -r memory.max=500M myGroup
sudo cgset -r memory.swap.max=0 myGroup
sudo chmod o+w /sys/fs/cgroup/cgroup.procs
cgexec -g memory:myGroup mycmd arg0 arg1
The line:
sudo chmod o+w /sys/fs/cgroup/cgroup.procs
is needed for it to work without sudo
: https://askubuntu.com/questions/1406329/how-to-run-cgexec-without-sudo-as-current-user-on-ubuntu-22-04-with-cgroups-v2/1450845#1450845 otherwise it fails with:
cgroup change of group failed
If you don't run that command, you can also use:
sudo cgexec -g memory:myGroup mycmd arg0 arg1
but then that runs as root
, which you usually don't want it to do, this can be tested with sudo cgexec -g memory:myGroup id
.
Compared to https://unix.stackexchange.com/a/125024/32558 which was originally for v1:
/sys/fs/cgroup/memory/myGroup/memory.limit_in_bytes
is now /sys/fs/cgroup/myGroup/memory.max
/sys/fs/cgroup/memory/myGroup/memory.memsw.limit_in_bytes
was split, now you just set the swap separatelly in /sys/fs/cgroup/myGroup/memory.swap.max
rather than the sum
For the specific case of memory however, just use systemd-run
as mentioned at: https://unix.stackexchange.com/a/536046/32558 that just worked and is by far the simplest approach.
Testing it out
malloc_touch.c
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
size_t nbytes, step;
if (argc > 1) {
nbytes = strtoull(argv[1], NULL, 0);
} else {
nbytes = 0x10;
}
if (argc > 2) {
step = strtoull(argv[2], NULL, 0);
} else {
step = 1;
}
char *base = malloc(nbytes);
assert(base);
char *i = base;
while (i < base + nbytes) {
*i = 13;
i += step;
}
return EXIT_SUCCESS;
}
GitHub upstream.
First we find that 1M
is about the minimum at which a C hello world will run:
sudo cgset -r memory.max=1M myGroup
cgexec -g memory:myGroup ./malloc_touch.out
Then starting from there we can try to malloc 100k:
sudo cgset -r memory.max=1M myGroup
cgexec -g memory:myGroup ./malloc_touch.out 100000
OK, there was still some left. Then if try 1M:
sudo cgset -r memory.max=1M myGroup
cgexec -g memory:myGroup ./malloc_touch.out 1000000
Killed as expected. Increase limit to 10M:
sudo cgset -r memory.max=10M myGroup
cgexec -g memory:myGroup ./malloc_touch.out 1000000
OK. Malloc 9M:
sudo cgset -r memory.max=10M myGroup
cgexec -g memory:myGroup ./malloc_touch.out 9000000
OK. Malloc 10M:
sudo cgset -r memory.max=10M myGroup
cgexec -g memory:myGroup ./malloc_touch.out 10000000
OK. Humm, not sure why, expected it to die. MiB vs MB? Try 11M
sudo cgset -r memory.max=10M myGroup
cgexec -g memory:myGroup ./malloc_touch.out 11000000
Killed as expected.
Tested on Ubuntu 22.10.
cgcreate is completely broken on Ubuntu 21.10
https://askubuntu.com/questions/1376093/is-cgroup-tools-using-cgroup-v1-or-v2
Fails with:
cgcreate: libcgroup initialization failed: Cgroup is not mounted
Apparently they moved part of the system to v2 but not the other.
docker
?