Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions example_problems/hello/submissions/wrong_answer/test-cpu-pinning.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* This code forks 10 children and checks that those run on the same
* CPU core as the parent. Since we're normally doing CPU pinning,
* this should be true and the program generates a WRONG-ANWSER.
* If there's a mismatch the program will trigger a RUNTIME-ERROR.
*
* @EXPECTED_RESULTS@: WRONG-ANSWER
*/

#include <errno.h>
#include <unistd.h>
#include <sched.h>
#include <stdio.h>
#include <string.h>
#include <sys/wait.h>

extern int errno;

int main()
{
unsigned int parent_cpu, cpu;
getcpu(&parent_cpu, NULL);
printf("Parent on CPU %d\n", parent_cpu);
fflush(NULL);

for(int i=0; i<10; i++) {
if ( fork()==0 ) {
// We're in the child
getcpu(&cpu, NULL);
printf("Child %d on CPU %d\n", i, cpu);
fflush(NULL);
if ( cpu!=parent_cpu ) {
printf("CPU MISMATCH!\n");
fflush(NULL);
return 1;
}
return 0;
}
}

// Wait for all our children
do {
pid_t pid;
int status;
pid = wait(&status);
if ( pid==-1 ) {
if ( errno==ECHILD ) {
printf("Done waiting for all children\n");
} else {
printf("Error in wait: %s\n", strerror(errno));
}
fflush(NULL);
break;
}
if ( pid>0 ) {
if ( !WIFEXITED(status) ) {
printf("Child pid %d terminated abnormally\n", (int)pid);
fflush(NULL);
return 1;
}
if ( WEXITSTATUS(status)!=0 ) {
printf("Child pid %d terminated with exit status %d\n",
(int)pid, (int)WEXITSTATUS(status));
return 1;
}
printf("Child pid %d terminated\n", (int)pid);
fflush(NULL);
}
} while ( 1 );

return 0;
}
80 changes: 61 additions & 19 deletions judge/runguard.cc
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@
#include <sched.h>
#include <sys/sysinfo.h>
#include <vector>
#include <set>
#include <sstream>
#include <string>
#include <utility>

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

std::set<unsigned> parse_cpuset(std::string cpus)
{
std::stringstream ss(cpus);
std::set<unsigned> result;

std::string token;
while ( getline(ss, token, ',') ) {
size_t split = token.find('-');
if ( split!=std::string::npos ) {
std::string token1 = token.substr(0, split);
std::string token2 = token.substr(split+1);
size_t len;
unsigned cpu1 = std::stoul(token1, &len);
if ( len<token1.length() ) error(0, "failed to parse cpuset `%s'", cpus.c_str());
unsigned cpu2 = std::stoul(token2, &len);
if ( len<token2.length() ) error(0, "failed to parse cpuset `%s'", cpus.c_str());
for(unsigned i=cpu1; i<=cpu2; i++) result.insert(i);
} else {
size_t len;
unsigned cpu = std::stoul(token, &len);
if ( len<token.length() ) error(0, "failed to parse cpuset `%s'", cpus.c_str());
result.insert(cpu);
}
}

return result;
}

std::set<unsigned> read_cpuset(const char *path)
{
FILE *file = fopen(path, "r");
if (file == nullptr) error(errno, "opening file `%s'", path);

char cpuset[1024];
if (fgets(cpuset, 1024, file) == nullptr) error(errno, "reading from file `%s'", path);

size_t len = strlen(cpuset);
if (len > 0 && cpuset[len-1] == '\n') cpuset[len-1] = 0;

if (fclose(file) != 0) error(errno, "closing file `%s'", path);

return parse_cpuset(cpuset);
}

void check_remaining_procs()
{
char path[1024];
Expand Down Expand Up @@ -494,9 +540,8 @@ void output_cgroup_stats_v1(double *cputime)
int ret;
if ((ret = cgroup_get_cgroup(cg)) != 0) error(ret,"get cgroup information");

int64_t max_usage;
struct cgroup_controller *cg_controller;
cg_controller = cgroup_get_controller(cg, "memory");
int64_t max_usage = 0;
struct cgroup_controller *cg_controller = cgroup_get_controller(cg, "memory");
ret = cgroup_get_value_int64(cg_controller, "memory.memsw.max_usage_in_bytes", &max_usage);
if ( ret!=0 ) error(ret,"get cgroup value memory.memsw.max_usage_in_bytes");

Expand All @@ -516,7 +561,7 @@ 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");
if ( (cg = cgroup_new_cgroup(cgroupname))==nullptr ) error(0,"cgroup_new_cgroup");

int ret;
if ((ret = cgroup_get_cgroup(cg)) != 0) error(ret,"get cgroup information");
Expand All @@ -540,7 +585,7 @@ void output_cgroup_stats_v2(double *cputime)
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);
long long usec = strtoll(stat.value, nullptr, 10);
*cputime = usec / 1e6;
}
ret = cgroup_read_stats_next(&handle, &stat);
Expand All @@ -549,7 +594,6 @@ void output_cgroup_stats_v2(double *cputime)
cgroup_read_stats_end(&handle);

cgroup_free(&cg);

}

/* Temporary shorthand define for error handling. */
Expand Down Expand Up @@ -901,7 +945,7 @@ void setrestrictions()

/* Put the child process in the cgroup */
if (is_cgroup_v2) {
const char *controllers[] = { "memory", NULL };
const char *controllers[] = { "memory", nullptr };
if (cgroup_change_cgroup_path(cgroupname, getpid(), controllers) != 0) {
error(0, "Failed to move the process to the cgroup");
}
Expand Down Expand Up @@ -950,7 +994,7 @@ void setrestrictions()
/* Set group-id (must be root for this, so before setting user). */
if ( use_group ) {
if ( setgid(rungid) ) error(errno,"cannot set group ID to `%d'",rungid);
if ( setgroups(0, NULL) ) error(errno,"cannot clear auxiliary groups");
if ( setgroups(0, nullptr) ) error(errno,"cannot clear auxiliary groups");

verbose("using group ID `%d'",rungid);
}
Expand Down Expand Up @@ -1116,7 +1160,7 @@ int main(int argc, char **argv)
case 'u': /* user option: uid or string */
use_user = 1;
runuser = strdup(optarg);
if ( runuser==NULL ) error(errno,"strdup() failed");
if ( runuser==nullptr ) error(errno,"strdup() failed");
errno = 0;
runuid = strtol(optarg,&ptr,10);
if ( errno || *ptr!='\0' ) {
Expand All @@ -1133,7 +1177,7 @@ int main(int argc, char **argv)
case 'g': /* group option: gid or string */
use_group = 1;
rungroup = strdup(optarg);
if ( rungroup==NULL ) error(errno,"strdup() failed");
if ( rungroup==nullptr ) error(errno,"strdup() failed");
errno = 0;
rungid = strtol(optarg,&ptr,10);
if ( errno || *ptr!='\0' ) rungid = groupid(optarg);
Expand Down Expand Up @@ -1298,14 +1342,12 @@ int main(int argc, char **argv)
}

if ( cpuset!=nullptr && strlen(cpuset)>0 ) {
int ret = strtol(cpuset, &ptr, 10);
/* check if input is only a single integer */
if ( *ptr == '\0' ) {
/* check if we have enough cores available */
int nprocs = get_nprocs_conf();
if ( ret < 0 || ret >= nprocs ) {
error(0, "processor ID %d given as cpuset, but only %d cores configured",
ret, nprocs);
std::set<unsigned> cpus = parse_cpuset(cpuset);
std::set<unsigned> online_cpus = read_cpuset("/sys/devices/system/cpu/online");

for(unsigned cpu : cpus) {
if ( !online_cpus.count(cpu) ) {
error(0, "requested pinning on CPU %u which is not online", cpu);
}
}
}
Expand Down Expand Up @@ -1488,7 +1530,7 @@ int main(int argc, char **argv)
}
}

int r = pselect(nfds+1, &readfds, nullptr, NULL, NULL, &emptymask);
int r = pselect(nfds+1, &readfds, nullptr, nullptr, nullptr, &emptymask);
if ( r==-1 && errno!=EINTR ) error(errno,"waiting for child data");
if (error_in_signalhandler) {
error(errno, "error in signal handler, exiting");
Expand Down
Loading