Skip to content

Commit d2e8b6e

Browse files
committed
Remove support for cgroup v1.
All relevant environments (Debian, Ubuntu, RedHat, ArchLinux, WSL2, Fedora) support and default to cgroup v2 since years, and it helps with simplification of runguard, which is a precursor of merging runpipe and runguard.
1 parent 528609a commit d2e8b6e

File tree

3 files changed

+28
-160
lines changed

3 files changed

+28
-160
lines changed

doc/manual/install-judgehost.rst

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -169,9 +169,9 @@ no separate measures are necessary, and they allow running
169169
:ref:`multiple judgedaemons <multiple-judgedaemons>`
170170
on a multi-core machine by using CPU binding.
171171

172-
The judgedaemon needs to run a recent Linux kernel (at least 3.2.0). The
173-
following steps configure cgroups on Debian. Instructions for other
174-
distributions may be different (send us your feedback!).
172+
The judgedaemon needs to run a recent Linux kernel (at least 5.19 or 6.0 or
173+
later). The following steps configure cgroups v2 on Debian. Instructions for
174+
other distributions may be different (send us your feedback!).
175175

176176
Edit grub config to add cgroup memory and swap accounting to the boot
177177
options. Edit ``/etc/default/grub`` and change the default
@@ -181,12 +181,6 @@ Optionally the timings can be made more stable by not letting the OS schedule
181181
any other tasks on the same CPU core the judgedaemon is using:
182182
``GRUB_CMDLINE_LINUX_DEFAULT="quiet cgroup_enable=memory swapaccount=1 isolcpus=2"``
183183

184-
On modern systems where cgroup v2 is available, DOMjudge will try to
185-
use that. This requires kernel versions 5.19 or 6.0 or later to
186-
support reporting peak memory usage. If not found, the system will try
187-
to fall back to cgroup v1, but this might require you to add
188-
``systemd.unified_cgroup_hierarchy=0`` to the boot options as well.
189-
190184
You have now configured the system to use cgroups. To create
191185
the actual cgroups that DOMjudge will use you need to run::
192186

judge/create_cgroups.in

Lines changed: 4 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,7 @@ if [ "$fs_type" = "cgroup2" ]; then
2525
major=$(echo "$kernel_version" | cut -d '.' -f 1)
2626
minor=$(echo "$kernel_version" | cut -d '.' -f 2)
2727
if [ "$major" -lt 5 ] || { [ "$major" -eq 5 ] && [ "$minor" -lt 19 ]; }; then
28-
cgroup_error_and_usage "Error: kernel ($kernel_version) is too old to record peak RAM usage with cgroup V2.
29-
You can try using cgroup V1 by adding systemd.unified_cgroup_hierarchy=0 to the kernel params."
28+
cgroup_error_and_usage "Error: kernel ($kernel_version) is too old to record peak RAM usage with cgroup V2."
3029
fi
3130
if ! echo "+memory" >> /sys/fs/cgroup/cgroup.subtree_control; then
3231
cgroup_error_and_usage "Error: Cannot add +memory to cgroup.subtree_control; check kernel params."
@@ -37,26 +36,6 @@ You can try using cgroup V1 by adding systemd.unified_cgroup_hierarchy=0 to the
3736
if grep -q ":/$" /proc/self/cgroup; then
3837
cgroup_error_and_usage "Error: Cgroups not configured properly, missing cgroup hierarchy prefix under /proc/self/cgroup. If running in a container, make sure to set cgroupns=host."
3938
fi
40-
41-
else # Trying cgroup V1:
42-
43-
for i in cpuset memory; do
44-
mkdir -p $CGROUPBASE/$i
45-
if [ ! -d $CGROUPBASE/$i/ ]; then
46-
if ! mount -t cgroup -o$i $i $CGROUPBASE/$i/; then
47-
cgroup_error_and_usage "Error: Can not mount $i cgroup. Probably cgroup support is missing from running kernel."
48-
fi
49-
fi
50-
mkdir -p $CGROUPBASE/$i/domjudge
51-
done
52-
53-
if [ ! -f $CGROUPBASE/memory/memory.limit_in_bytes ] || [ ! -f $CGROUPBASE/memory/memory.memsw.limit_in_bytes ]; then
54-
cgroup_error_and_usage "Error: cgroup support missing memory features in running kernel."
55-
fi
56-
57-
chown -R $JUDGEHOSTUSER $CGROUPBASE/*/domjudge
58-
59-
cat $CGROUPBASE/cpuset/cpuset.cpus > $CGROUPBASE/cpuset/domjudge/cpuset.cpus
60-
cat $CGROUPBASE/cpuset/cpuset.mems > $CGROUPBASE/cpuset/domjudge/cpuset.mems
61-
62-
fi # cgroup V1
39+
else
40+
cgroup_error_and_usage "Error: Cgroups not configured properly, did not find cgroup v2 in /sys/fs/cgroup but '$fs_type'."
41+
fi

judge/runguard.cc

Lines changed: 21 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -145,8 +145,6 @@ int show_version;
145145
int in_error_handling = 0;
146146
pid_t runpipe_pid = -1;
147147

148-
bool is_cgroup_v2 = false;
149-
150148
double walltimelimit[2], cputimelimit[2]; /* in seconds, soft and hard limits */
151149
int walllimit_reached, cpulimit_reached; /* 1=soft, 2=hard, 3=both limits reached */
152150
rlim_t memsize;
@@ -514,11 +512,7 @@ std::set<unsigned> read_cpuset(const char *path)
514512
void check_remaining_procs()
515513
{
516514
char path[1024];
517-
if (is_cgroup_v2) {
518-
snprintf(path, 1023, "/sys/fs/cgroup/%s/cgroup.procs", cgroupname);
519-
} else {
520-
snprintf(path, 1023, "/sys/fs/cgroup/cpuacct/%s/cgroup.procs", cgroupname);
521-
}
515+
snprintf(path, 1023, "/sys/fs/cgroup/%s/cgroup.procs", cgroupname);
522516

523517
FILE *file = fopen(path, "r");
524518
if (file == nullptr) {
@@ -532,33 +526,8 @@ void check_remaining_procs()
532526
if (fclose(file) != 0) error(errno, "closing file `%s'", path);
533527
}
534528

535-
void output_cgroup_stats_v1(double *cputime)
536-
{
537-
struct cgroup *cg;
538-
if ( (cg = cgroup_new_cgroup(cgroupname))==nullptr ) error(0,"cgroup_new_cgroup");
539-
540-
int ret;
541-
if ((ret = cgroup_get_cgroup(cg)) != 0) error(ret,"get cgroup information");
542-
543-
int64_t max_usage = 0;
544-
struct cgroup_controller *cg_controller = cgroup_get_controller(cg, "memory");
545-
ret = cgroup_get_value_int64(cg_controller, "memory.memsw.max_usage_in_bytes", &max_usage);
546-
if ( ret!=0 ) error(ret,"get cgroup value memory.memsw.max_usage_in_bytes");
547-
548-
verbose("total memory used: %" PRId64 " kB", max_usage/1024);
549-
write_meta("memory-bytes","%" PRId64, max_usage);
550-
551-
int64_t cpu_time_int;
552-
cg_controller = cgroup_get_controller(cg, "cpuacct");
553-
ret = cgroup_get_value_int64(cg_controller, "cpuacct.usage", &cpu_time_int);
554-
if ( ret!=0 ) error(ret,"get cgroup value cpuacct.usage");
555529

556-
*cputime = (double) cpu_time_int / 1.e9;
557-
558-
cgroup_free(&cg);
559-
}
560-
561-
void output_cgroup_stats_v2(double *cputime)
530+
void output_cgroup_stats(double *cputime)
562531
{
563532
struct cgroup *cg;
564533
if ( (cg = cgroup_new_cgroup(cgroupname))==nullptr ) error(0,"cgroup_new_cgroup");
@@ -615,18 +584,13 @@ void cgroup_create()
615584
}
616585

617586
int ret;
618-
if (is_cgroup_v2) {
619-
// TODO: do we want to set cpu.weight here as well?
620-
if (memsize != RLIM_INFINITY) {
621-
cgroup_add_value(uint64, "memory.max", memsize);
622-
cgroup_add_value(uint64, "memory.swap.max", 0);
623-
} else {
624-
cgroup_add_value(string, "memory.max", "max");
625-
cgroup_add_value(string, "memory.swap.max", "max");
626-
}
587+
// TODO: do we want to set cpu.weight here as well?
588+
if (memsize != RLIM_INFINITY) {
589+
cgroup_add_value(uint64, "memory.max", memsize);
590+
cgroup_add_value(uint64, "memory.swap.max", 0);
627591
} else {
628-
cgroup_add_value(uint64, "memory.limit_in_bytes", memsize);
629-
cgroup_add_value(uint64, "memory.memsw.limit_in_bytes", memsize);
592+
cgroup_add_value(string, "memory.max", "max");
593+
cgroup_add_value(string, "memory.swap.max", "max");
630594
}
631595

632596
/* Set up cpu restrictions; we pin the task to a specific set of
@@ -645,15 +609,6 @@ void cgroup_create()
645609
verbose("cpuset undefined");
646610
}
647611

648-
if (!is_cgroup_v2) {
649-
if ( (cg_controller = cgroup_add_controller(cg, "cpu"))==nullptr ) {
650-
error(0,"cgroup_add_controller cpu");
651-
}
652-
if ((cg_controller = cgroup_add_controller(cg, "cpuacct")) == nullptr) {
653-
error(0, "cgroup_add_controller cpuacct");
654-
}
655-
}
656-
657612
/* Perform the actual creation of the cgroup */
658613
if ( (ret = cgroup_create_cgroup(cg, 1))!=0 ) error(ret,"creating cgroup");
659614

@@ -663,46 +618,21 @@ void cgroup_create()
663618

664619
#undef cgroup_setval
665620

666-
void cgroup_attach()
667-
{
668-
struct cgroup *cg;
669-
cg = cgroup_new_cgroup(cgroupname);
670-
if (!cg) error(0,"cgroup_new_cgroup");
671-
672-
int ret;
673-
if ( (ret = cgroup_get_cgroup(cg))!=0 ) error(ret,"get cgroup information");
674-
675-
/* Attach task to the cgroup */
676-
if ( (ret = cgroup_attach_task(cg))!=0 ) error(ret,"attach task to cgroup");
677-
678-
cgroup_free(&cg);
679-
}
680621

681622
void cgroup_kill()
682623
{
683624
/* kill any remaining tasks, and wait for them to be gone */
684625
char mem_controller[10] = "memory";
685-
if (is_cgroup_v2) {
686-
int size;
687-
do {
688-
pid_t* pids;
689-
int ret = cgroup_get_procs(cgroupname, mem_controller, &pids, &size);
690-
if (ret != 0) error(ret, "cgroup_get_procs");
691-
for(int i = 0; i < size; i++) {
692-
kill(pids[i], SIGKILL);
693-
}
694-
free(pids);
695-
} while (size > 0);
696-
} else {
697-
while(1) {
698-
void *handle = nullptr;
699-
pid_t pid;
700-
int ret = cgroup_get_task_begin(cgroupname, mem_controller, &handle, &pid);
701-
cgroup_get_task_end(&handle);
702-
if (ret == ECGEOF) break;
703-
kill(pid, SIGKILL);
626+
int size;
627+
do {
628+
pid_t* pids;
629+
int ret = cgroup_get_procs(cgroupname, mem_controller, &pids, &size);
630+
if (ret != 0) error(ret, "cgroup_get_procs");
631+
for(int i = 0; i < size; i++) {
632+
kill(pids[i], SIGKILL);
704633
}
705-
}
634+
free(pids);
635+
} while (size > 0);
706636
}
707637

708638
void cgroup_delete()
@@ -712,9 +642,6 @@ void cgroup_delete()
712642
if (!cg) error(0,"cgroup_new_cgroup");
713643

714644
if (cgroup_add_controller(cg, "cpu") == nullptr) error(0, "cgroup_add_controller cpu");
715-
if (!is_cgroup_v2) {
716-
if (cgroup_add_controller(cg, "cpuacct") == nullptr) error(0, "cgroup_add_controller cpuacct");
717-
}
718645
if ( cgroup_add_controller(cg, "memory")==nullptr ) error(0,"cgroup_add_controller memory");
719646

720647
if ( cpuset!=nullptr && strlen(cpuset)>0 ) {
@@ -958,13 +885,9 @@ void setrestrictions()
958885
}
959886

960887
/* Put the child process in the cgroup */
961-
if (is_cgroup_v2) {
962-
const char *controllers[] = { "memory", nullptr };
963-
if (cgroup_change_cgroup_path(cgroupname, getpid(), controllers) != 0) {
964-
error(0, "Failed to move the process to the cgroup");
965-
}
966-
} else {
967-
cgroup_attach();
888+
const char *controllers[] = { "memory", nullptr };
889+
if (cgroup_change_cgroup_path(cgroupname, getpid(), controllers) != 0) {
890+
error(0, "Failed to move the process to the cgroup");
968891
}
969892

970893
/* Run the command in a separate process group so that the command
@@ -1109,28 +1032,6 @@ void pump_pipes(fd_set* readfds, size_t data_read[], size_t data_passed[])
11091032

11101033
}
11111034

1112-
bool cgroup_is_v2() {
1113-
bool ret = false;
1114-
FILE *fp = setmntent("/proc/mounts", "r");
1115-
if (!fp) {
1116-
perror("Error opening /proc/mounts");
1117-
return false;
1118-
}
1119-
1120-
struct mntent *entry;
1121-
while ((entry = getmntent(fp)) != nullptr) {
1122-
if (strcmp(entry->mnt_dir, "/sys/fs/cgroup") == 0) {
1123-
if (strcmp(entry->mnt_type, "cgroup2") == 0) {
1124-
ret = true;
1125-
}
1126-
break;
1127-
}
1128-
}
1129-
1130-
endmntent(fp);
1131-
1132-
return ret;
1133-
}
11341035

11351036
int main(int argc, char **argv)
11361037
{
@@ -1306,8 +1207,6 @@ int main(int argc, char **argv)
13061207
cmdname = argv[optind];
13071208
cmdargs = argv+optind;
13081209

1309-
is_cgroup_v2 = cgroup_is_v2();
1310-
13111210
if ( outputmeta && (metafile = fopen(metafilename,"w"))==nullptr ) {
13121211
error(errno,"cannot open `%s'",metafilename);
13131212
}
@@ -1630,11 +1529,7 @@ int main(int argc, char **argv)
16301529
check_remaining_procs();
16311530

16321531
double cputime = -1;
1633-
if (is_cgroup_v2) {
1634-
output_cgroup_stats_v2(&cputime);
1635-
} else {
1636-
output_cgroup_stats_v1(&cputime);
1637-
}
1532+
output_cgroup_stats(&cputime);
16381533
cgroup_kill();
16391534
cgroup_delete();
16401535

0 commit comments

Comments
 (0)