Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 9a40bbe

Browse files
committed
Parse cpuset parameter and online CPUs and fail to use offline CPUs
When you try to pin a cgroup to a CPU that is offline, then the call to cgroups works fine, but then the Linux kernel just schedules the processes in that cgroup on any available CPU. That's definitely not what we want, so explicitly check and error out when the requested CPUs are not online.
1 parent 2900a4e commit 9a40bbe

File tree

1 file changed

+52
-8
lines changed

1 file changed

+52
-8
lines changed

‎judge/runguard.cc

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@
6363
#include <sched.h>
6464
#include <sys/sysinfo.h>
6565
#include <vector>
66+
#include <set>
67+
#include <sstream>
6668
#include <string>
6769
#include <utility>
6870

@@ -465,6 +467,50 @@ void output_exit_time(int exitcode, double cpudiff)
465467
write_meta("time-result","%s",output_timelimit_str[timelimit_reached]);
466468
}
467469

470+
std::set<unsigned> parse_cpuset(std::string cpus)
471+
{
472+
std::stringstream ss(cpus);
473+
std::set<unsigned> result;
474+
475+
std::string token;
476+
while ( getline(ss, token, ',') ) {
477+
size_t split = token.find('-');
478+
if ( split!=std::string::npos ) {
479+
std::string token1 = token.substr(0, split);
480+
std::string token2 = token.substr(split+1);
481+
size_t len;
482+
unsigned cpu1 = std::stoul(token1, &len);
483+
if ( len<token1.length() ) error(0, "failed to parse cpuset `%s'", cpus.c_str());
484+
unsigned cpu2 = std::stoul(token2, &len);
485+
if ( len<token2.length() ) error(0, "failed to parse cpuset `%s'", cpus.c_str());
486+
for(unsigned i=cpu1; i<=cpu2; i++) result.insert(i);
487+
} else {
488+
size_t len;
489+
unsigned cpu = std::stoul(token, &len);
490+
if ( len<token.length() ) error(0, "failed to parse cpuset `%s'", cpus.c_str());
491+
result.insert(cpu);
492+
}
493+
}
494+
495+
return result;
496+
}
497+
498+
std::set<unsigned> read_cpuset(const char *path)
499+
{
500+
FILE *file = fopen(path, "r");
501+
if (file == nullptr) error(errno, "opening file `%s'", path);
502+
503+
char cpuset[1024];
504+
if (fgets(cpuset, 1024, file) == nullptr) error(errno, "reading from file `%s'", path);
505+
506+
size_t len = strlen(cpuset);
507+
if (len > 0 && cpuset[len-1] == '\n') cpuset[len-1] = 0;
508+
509+
if (fclose(file) != 0) error(errno, "closing file `%s'", path);
510+
511+
return parse_cpuset(cpuset);
512+
}
513+
468514
void check_remaining_procs()
469515
{
470516
char path[1024];
@@ -1296,14 +1342,12 @@ int main(int argc, char **argv)
12961342
}
12971343

12981344
if ( cpuset!=nullptr && strlen(cpuset)>0 ) {
1299-
int ret = strtol(cpuset, &ptr, 10);
1300-
/* check if input is only a single integer */
1301-
if ( *ptr == '0円' ) {
1302-
/* check if we have enough cores available */
1303-
int nprocs = get_nprocs_conf();
1304-
if ( ret < 0 || ret >= nprocs ) {
1305-
error(0, "processor ID %d given as cpuset, but only %d cores configured",
1306-
ret, nprocs);
1345+
std::set<unsigned> cpus = parse_cpuset(cpuset);
1346+
std::set<unsigned> online_cpus = read_cpuset("/sys/devices/system/cpu/online");
1347+
1348+
for(unsigned cpu : cpus) {
1349+
if ( !online_cpus.count(cpu) ) {
1350+
error(0, "requested pinning on CPU %u which is not online", cpu);
13071351
}
13081352
}
13091353
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /