Skip to content

Commit

Permalink
fix
Browse files Browse the repository at this point in the history
  • Loading branch information
meisterT committed Aug 27, 2024
1 parent 526ba4f commit f65f320
Showing 1 changed file with 119 additions and 124 deletions.
243 changes: 119 additions & 124 deletions judge/runguard.cc
Original file line number Diff line number Diff line change
Expand Up @@ -308,15 +308,12 @@ void write_meta(const char *key, const char *format, ...)
va_start(ap,format);

if ( fprintf(metafile,"%s: ",key)<=0 ) {
outputmeta = 0;
error(0,"cannot write to file `%s'",metafilename);
}
if ( vfprintf(metafile,format,ap)<0 ) {
outputmeta = 0;
error(0,"cannot write to file `%s'(vfprintf)",metafilename);
}
if ( fprintf(metafile,"\n")<=0 ) {
outputmeta = 0;
error(0,"cannot write to file `%s'",metafilename);
}

Expand Down Expand Up @@ -439,11 +436,11 @@ void output_exit_time(int exitcode, double cpudiff)
void check_remaining_procs()
{
char path[1024];
if (is_cgroup_v2) {
snprintf(path, 1023, "/sys/fs/cgroup/%scgroup.procs", cgroupname);
} else {
snprintf(path, 1023, "/sys/fs/cgroup/cpuacct%scgroup.procs", cgroupname);
}
if (is_cgroup_v2) {
snprintf(path, 1023, "/sys/fs/cgroup/%scgroup.procs", cgroupname);
} else {
snprintf(path, 1023, "/sys/fs/cgroup/cpuacct%scgroup.procs", cgroupname);
}

FILE *file = fopen(path, "r");
if (file == nullptr) {
Expand Down Expand Up @@ -486,40 +483,40 @@ void output_cgroup_stats_v1(double *cputime)

void output_cgroup_stats_v2(double *cputime)
{
struct cgroup *cg;
if ( (cg = cgroup_new_cgroup(cgroupname))==NULL ) error(0,"cgroup_new_cgroup");

int ret;
if ((ret = cgroup_get_cgroup(cg)) != 0) error(ret,"get cgroup information");

struct cgroup_controller *cg_controller = cgroup_get_controller(cg, "memory");
int64_t max_usage = 0;
ret = cgroup_get_value_int64(cg_controller, "memory.peak", &max_usage);
if ( ret == ECGROUPVALUENOTEXIST ) {
write_meta("internal-warning", "Kernel too old and does not support memory.peak");
} else if ( ret!=0 ) {
error(ret,"get cgroup value memory.peak");
}

// There is no need to check swap usage, as we limit it to 0.
verbose("total memory used: %" PRId64 " kB", max_usage/1024);
write_meta("memory-bytes","%" PRId64, max_usage);

struct cgroup_stat stat;
void *handle;
ret = cgroup_read_stats_begin("cpu", cgroupname, &handle, &stat);
while (ret == 0) {
verbose("cpu.stat: %s = %s", stat.name, stat.value);
if (strcmp(stat.name, "usage_usec") == 0) {
long long usec = strtoll(stat.value, NULL, 10);
*cputime = usec / 1e6;
}
ret = cgroup_read_stats_next(&handle, &stat);
}
if ( ret!=ECGEOF ) error(ret,"get cgroup value cpu.stat");
cgroup_read_stats_end(&handle);

cgroup_free(&cg);
struct cgroup *cg;
if ( (cg = cgroup_new_cgroup(cgroupname))==NULL ) error(0,"cgroup_new_cgroup");

int ret;
if ((ret = cgroup_get_cgroup(cg)) != 0) error(ret,"get cgroup information");

struct cgroup_controller *cg_controller = cgroup_get_controller(cg, "memory");
int64_t max_usage = 0;
ret = cgroup_get_value_int64(cg_controller, "memory.peak", &max_usage);
if ( ret == ECGROUPVALUENOTEXIST ) {
write_meta("internal-warning", "Kernel too old and does not support memory.peak");
} else if ( ret!=0 ) {
error(ret,"get cgroup value memory.peak");
}

// There is no need to check swap usage, as we limit it to 0.
verbose("total memory used: %" PRId64 " kB", max_usage/1024);
write_meta("memory-bytes","%" PRId64, max_usage);

struct cgroup_stat stat;
void *handle;
ret = cgroup_read_stats_begin("cpu", cgroupname, &handle, &stat);
while (ret == 0) {
verbose("cpu.stat: %s = %s", stat.name, stat.value);
if (strcmp(stat.name, "usage_usec") == 0) {
long long usec = strtoll(stat.value, NULL, 10);
*cputime = usec / 1e6;
}
ret = cgroup_read_stats_next(&handle, &stat);
}
if ( ret!=ECGEOF ) error(ret,"get cgroup value cpu.stat");
cgroup_read_stats_end(&handle);

cgroup_free(&cg);

}

Expand All @@ -541,21 +538,21 @@ void cgroup_create()
error(0,"cgroup_add_controller memory");
}

int ret;
if (is_cgroup_v2) {
// TODO: do we want to set cpu.weight here as well?
if (memsize != RLIM_INFINITY) {
cgroup_add_value(int64, "memory.max", memsize);
// TODO: Is this the behavior change that JohnB mentioned?
cgroup_add_value(int64, "memory.swap.max", 0);
} else {
cgroup_add_value(string, "memory.max", "max");
cgroup_add_value(string, "memory.swap.max", "max");
}
} else {
cgroup_add_value(int64, "memory.limit_in_bytes", memsize);
cgroup_add_value(int64, "memory.memsw.limit_in_bytes", memsize);
}
int ret;
if (is_cgroup_v2) {
// TODO: do we want to set cpu.weight here as well?
if (memsize != RLIM_INFINITY) {
cgroup_add_value(int64, "memory.max", memsize);
// TODO: Is this the behavior change that JohnB mentioned?
cgroup_add_value(int64, "memory.swap.max", 0);
} else {
cgroup_add_value(string, "memory.max", "max");
cgroup_add_value(string, "memory.swap.max", "max");
}
} else {
cgroup_add_value(int64, "memory.limit_in_bytes", memsize);
cgroup_add_value(int64, "memory.memsw.limit_in_bytes", memsize);
}

/* Set up cpu restrictions; we pin the task to a specific set of
cpus. We also give it exclusive access to those cores, and set
Expand Down Expand Up @@ -608,28 +605,28 @@ void cgroup_attach()

void cgroup_kill()
{
/* kill any remaining tasks, and wait for them to be gone */
if (is_cgroup_v2) {
int size;
do {
pid_t* pids;
int ret = cgroup_get_procs(cgroupname, "memory", &pids, &size);
if (ret != 0) error(ret, "cgroup_get_procs");
for(int i = 0; i < size; i++) {
kill(pids[i], SIGKILL);
}
free(pids);
} while (size > 0);
} else {
while(1) {
void *handle = nullptr;
pid_t pid;
int ret = cgroup_get_task_begin(cgroupname, "memory", &handle, &pid);
cgroup_get_task_end(&handle);
if (ret == ECGEOF) break;
kill(pid, SIGKILL);
}
}
/* kill any remaining tasks, and wait for them to be gone */
if (is_cgroup_v2) {
int size;
do {
pid_t* pids;
int ret = cgroup_get_procs(cgroupname, "memory", &pids, &size);
if (ret != 0) error(ret, "cgroup_get_procs");
for(int i = 0; i < size; i++) {
kill(pids[i], SIGKILL);
}
free(pids);
} while (size > 0);
} else {
while(1) {
void *handle = nullptr;
pid_t pid;
int ret = cgroup_get_task_begin(cgroupname, "memory", &handle, &pid);
cgroup_get_task_end(&handle);
if (ret == ECGEOF) break;
kill(pid, SIGKILL);
}
}
}

void cgroup_delete()
Expand All @@ -638,19 +635,19 @@ void cgroup_delete()
cg = cgroup_new_cgroup(cgroupname);
if (!cg) error(0,"cgroup_new_cgroup");

if (cgroup_add_controller(cg, "cpu") == nullptr) error(0, "cgroup_add_controller cpu");
if (!is_cgroup_v2) {
if (cgroup_add_controller(cg, "cpuacct") == nullptr) error(0, "cgroup_add_controller cpuacct");
}
if (cgroup_add_controller(cg, "cpu") == nullptr) error(0, "cgroup_add_controller cpu");
if (!is_cgroup_v2) {
if (cgroup_add_controller(cg, "cpuacct") == nullptr) error(0, "cgroup_add_controller cpuacct");
}
if ( cgroup_add_controller(cg, "memory")==nullptr ) error(0,"cgroup_add_controller memory");

if ( cpuset!=nullptr && strlen(cpuset)>0 ) {
if ( cgroup_add_controller(cg, "cpuset")==nullptr ) error(0,"cgroup_add_controller cpuset");
}
/* Clean up our cgroup */
nanosleep(&cg_delete_delay,nullptr);
int ret = cgroup_delete_cgroup_ext(cg, CGFLAG_DELETE_IGNORE_MIGRATION | CGFLAG_DELETE_RECURSIVE);
// TODO: is this actually benign?
int ret = cgroup_delete_cgroup_ext(cg, CGFLAG_DELETE_IGNORE_MIGRATION | CGFLAG_DELETE_RECURSIVE);
// TODO: is this actually benign to ignore ECGOTHER here?
if ( ret!=0 && ret!=ECGOTHER ) error(ret,"deleting cgroup");

cgroup_free(&cg);
Expand Down Expand Up @@ -865,14 +862,14 @@ void setrestrictions()
}

/* Put the child process in the cgroup */
if (is_cgroup_v2) {
const char *controllers[] = { "memory", NULL };
if (cgroup_change_cgroup_path(cgroupname, getpid(), controllers) != 0) {
error(0, "Failed to move the process to the cgroup");
}
} else {
cgroup_attach();
}
if (is_cgroup_v2) {
const char *controllers[] = { "memory", NULL };
if (cgroup_change_cgroup_path(cgroupname, getpid(), controllers) != 0) {
error(0, "Failed to move the process to the cgroup");
}
} else {
cgroup_attach();
}

/* Run the command in a separate process group so that the command
and all its children can be killed off with one signal. */
Expand Down Expand Up @@ -1019,26 +1016,26 @@ void pump_pipes(fd_set* readfds, size_t data_read[], size_t data_passed[])
}

bool cgroup_is_v2() {
bool ret = false;
FILE *fp = setmntent("/proc/mounts", "r");
if (!fp) {
perror("Error opening /proc/mounts");
return false;
}

struct mntent *entry;
while ((entry = getmntent(fp)) != nullptr) {
if (strcmp(entry->mnt_dir, "/sys/fs/cgroup") == 0) {
if (strcmp(entry->mnt_type, "cgroup2") == 0) {
ret = true;
}
break;
}
}

endmntent(fp);

return ret;
bool ret = false;
FILE *fp = setmntent("/proc/mounts", "r");
if (!fp) {
perror("Error opening /proc/mounts");
return false;
}

struct mntent *entry;
while ((entry = getmntent(fp)) != nullptr) {
if (strcmp(entry->mnt_dir, "/sys/fs/cgroup") == 0) {
if (strcmp(entry->mnt_type, "cgroup2") == 0) {
ret = true;
}
break;
}
}

endmntent(fp);

return ret;
}

int main(int argc, char **argv)
Expand Down Expand Up @@ -1215,7 +1212,7 @@ int main(int argc, char **argv)
cmdname = argv[optind];
cmdargs = argv+optind;

is_cgroup_v2 = cgroup_is_v2();
is_cgroup_v2 = cgroup_is_v2();

if ( outputmeta && (metafile = fopen(metafilename,"w"))==nullptr ) {
error(errno,"cannot open `%s'",metafilename);
Expand Down Expand Up @@ -1277,8 +1274,6 @@ int main(int argc, char **argv)
}
}

// cgroup_set_default_logger(CGROUP_LOG_DEBUG);

/* Make libcgroup ready for use */
ret = cgroup_init();
if ( ret!=0 ) {
Expand All @@ -1292,8 +1287,8 @@ int main(int argc, char **argv)
} else {
str[0] = 0;
}
snprintf(cgroupname, 255, "domjudge/dj_cgroup_%d_%.16s_%d.%06d/",
getpid(), str, (int) progstarttime.tv_sec, (int) progstarttime.tv_usec);
snprintf(cgroupname, 255, "domjudge/dj_cgroup_%d_%.16s_%d.%06d/",
getpid(), str, (int) progstarttime.tv_sec, (int) progstarttime.tv_usec);

cgroup_create();

Expand Down Expand Up @@ -1358,7 +1353,7 @@ int main(int argc, char **argv)
error(errno,"cannot start `%s', limit: %ld/%ld | ",cmdname, limit.rlim_cur, limit.rlim_max);

default: /* become watchdog */
verbose("child pid = %d", child_pid);
verbose("child pid = %d", child_pid);
/* Shed privileges, only if not using a separate child uid,
because in that case we may need root privileges to kill
the child process. Do not use Linux specific setresuid()
Expand Down Expand Up @@ -1542,11 +1537,11 @@ int main(int argc, char **argv)
check_remaining_procs();

double cputime = -1;
if (is_cgroup_v2) {
output_cgroup_stats_v2(&cputime);
} else {
output_cgroup_stats_v1(&cputime);
}
if (is_cgroup_v2) {
output_cgroup_stats_v2(&cputime);
} else {
output_cgroup_stats_v1(&cputime);
}
cgroup_kill();
cgroup_delete();

Expand Down

0 comments on commit f65f320

Please sign in to comment.