Skip to content

Commit a77630d

Browse files
committed
Finished sandbox and cgroup
1 parent 45abd5d commit a77630d

File tree

19 files changed

+573
-130
lines changed

19 files changed

+573
-130
lines changed

.gitignore

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -110,10 +110,4 @@ node/bin
110110
# VSCode Config
111111
.vscode
112112

113-
# Test
114-
test/**/*.out
115-
test/**/result.yml
116-
test/**/compile.log
117-
test/**/exe
118-
119113
hoj-judger-config.yml

CMakeLists.txt

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,8 @@ add_subdirectory(${PROJECT_SOURCE_DIR}/third_party/yaml-cpp)
1313
add_executable(hoj-judger ${PROJECT_SRC_FILES})
1414
target_link_libraries(hoj-judger yaml-cpp pthread)
1515

16-
#add_custom_command(
17-
# TARGET hoj-judger
18-
# COMMAND cp ../third_party/hoj-testlib/bin/noip hoj-checker &&
19-
# cp hoj-judger ../node/bin/hoj-judger &&
20-
# cp hoj-checker ../node/bin/hoj-checker
21-
#)
16+
add_subdirectory(test/cgroup)
17+
add_subdirectory(test/sandbox)
18+
enable_testing()
19+
add_test(NAME test-cgroup COMMAND test-cgroup)
20+
add_test(NAME test-sandbox COMMAND test-sandbox)

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ yarn add hoj-judger
99
```
1010

1111
## Build by Yourself
12-
Requirement: CMake 3.4 or higher, g++ 8 or higher
12+
Requirement: CMake 3.4 or higher, g++ 9 or higher
1313
```bash
1414
./build.sh
1515
```

init-sandbox.sh

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,36 @@
1-
#!/bin/sh
1+
#!/bin/bash
22

33
set -o errexit
44

5-
if [ $1 ]; then path=${1%*/};
6-
else path="/opt/hoj-sandbox"; fi
5+
# Params:
6+
# $1: Sandbox directory path
7+
# $2: Mirror
78

8-
if [ -d $path ]; then rm -r $path; fi
9-
mkdir $path;
10-
mkdir $path/rootfs;
9+
if [ $1 ]; then sandbox_path=${1%*/};
10+
else sandbox_path="/opt/hoj-sandbox"; fi
11+
12+
if [ -d $sandbox_path ]; then rm -r $sandbox_path; fi
13+
mkdir $sandbox_path;
14+
mkdir $sandbox_path/rootfs;
1115

1216
# Mirrors:
17+
# - Alpine: http://dl-cdn.alpinelinux.org
1318
# - Tsinghua: https://mirrors.tuna.tsinghua.edu.cn
1419

15-
if [ $2 ]; then mirror=${2%*/};
16-
else mirror="http://dl-cdn.alpinelinux.org"; fi
17-
download=$mirror"/alpine/v3.8/releases/x86_64/alpine-minirootfs-3.8.0-x86_64.tar.gz"
20+
if [ $2 ]; then mirror_name="${2}";
21+
else mirror_name="alpine"; fi
22+
23+
if [ $mirror_name == "alpine" ]; then mirror_url="http://dl-cdn.alpinelinux.org";
24+
elif [ $mirror_name == "tuna" ]; then mirror_url="https://mirrors.tuna.tsinghua.edu.cn";
25+
elif [ $mirror_name == "custom" ]; then mirror_url=${3%*/}; fi
26+
27+
download=$mirror_url"/alpine/v3.13/releases/x86_64/alpine-minirootfs-3.13.2-x86_64.tar.gz"
28+
29+
curl -L $download | tar -xzf - -C $sandbox_path/rootfs
30+
31+
if [ $mirror_name == "tuna" ]; then
32+
sed -i 's/dl-cdn.alpinelinux.org/mirrors.tuna.tsinghua.edu.cn/g' $sandbox_path/rootfs/etc/apk/repositories
33+
fi
1834

19-
curl -L $download | tar -xzf - -C $path/rootfs
35+
# Set DNS
36+
echo -e 'nameserver 8.8.8.8\nnameserver 8.8.4.4' > $sandbox_path/rootfs/etc/resolv.conf

src/cgroup.cpp

Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
/*
2+
This file is part of the Hydrogen OJ Judger.
3+
4+
This program is free software: you can redistribute it and/or modify
5+
it under the terms of the GNU Affero General Public License as published
6+
by the Free Software Foundation, either version 3 of the License, or
7+
(at your option) any later version.
8+
9+
This program is distributed in the hope that it will be useful,
10+
but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
GNU Affero General Public License for more details.
13+
14+
You should have received a copy of the GNU Affero General Public License
15+
along with this program. If not, see <https://www.gnu.org/licenses/>.
16+
*/
17+
18+
/* Copyright (C) 2020-2021 Alex Cui */
19+
20+
#include "cgroup.h"
21+
22+
#include <cstdint>
23+
#include <cstdio>
24+
#include <cstdlib>
25+
#include <cstring>
26+
#include <filesystem>
27+
#include <fstream>
28+
#include <iostream>
29+
#include <map>
30+
#include <vector>
31+
32+
#include <mntent.h>
33+
34+
namespace fs = std::filesystem;
35+
36+
static std::map<std::string, std::vector<fs::path>> mount_table;
37+
static bool initialized = false;
38+
39+
int hoj::init_cgroup() {
40+
mount_table.clear();
41+
42+
std::ifstream proc_cgroup("/proc/cgroups");
43+
if (!proc_cgroup.is_open()) {
44+
// TODO: error
45+
}
46+
47+
std::string subsys_name;
48+
int hierarchy, num_cgroups, enabled;
49+
std::vector<std::string> controller;
50+
51+
proc_cgroup.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
52+
while (!proc_cgroup.eof()) {
53+
proc_cgroup >> subsys_name >> hierarchy >> num_cgroups >> enabled;
54+
controller.push_back(subsys_name);
55+
}
56+
57+
FILE *proc_mount = fopen("/proc/mounts", "re");
58+
if (proc_mount == nullptr) {
59+
// TODO: error
60+
}
61+
62+
mntent *ent = nullptr;
63+
mntent *temp_ent = new mntent;
64+
char mntent_buffer[4 * FILENAME_MAX];
65+
while (
66+
(ent = getmntent_r(
67+
proc_mount, temp_ent, mntent_buffer, sizeof(mntent_buffer))
68+
) != nullptr
69+
) {
70+
if (strcmp(ent->mnt_type, "cgroup")) {
71+
continue;
72+
}
73+
74+
for (const auto &name : controller) {
75+
char *mntopt = hasmntopt(ent, name.c_str());
76+
if (!mntopt) {
77+
continue;
78+
}
79+
80+
mount_table[name].push_back(ent->mnt_dir);
81+
}
82+
}
83+
84+
delete temp_ent;
85+
fclose(proc_mount);
86+
proc_cgroup.close();
87+
88+
initialized = true;
89+
90+
return 0;
91+
}
92+
93+
bool hoj::cgroup_initialized() {
94+
return initialized;
95+
}
96+
97+
static fs::path get_cgroup_path(const std::string &controller) {
98+
auto iter = mount_table.find(controller);
99+
if (iter == mount_table.end()) {
100+
// TODO: error
101+
return "";
102+
}
103+
104+
return iter->second[0];
105+
}
106+
107+
int hoj::create_cgroup(const hoj::cgroup_info &info) {
108+
for (const auto &controller : info.controller) {
109+
fs::create_directories(get_cgroup_path(controller) / info.name);
110+
}
111+
return 0;
112+
}
113+
114+
int hoj::remove_cgroup(const cgroup_info &info) {
115+
for (const auto &controller : info.controller) {
116+
auto target = get_cgroup_path(controller) / info.name;
117+
if (fs::exists(target)) {
118+
fs::remove(target);
119+
}
120+
}
121+
return 0;
122+
}
123+
124+
int hoj::check_cgroup(const cgroup_info &info) {
125+
for (const auto &controller : info.controller) {
126+
auto target = get_cgroup_path(controller) / info.name;
127+
if (fs::exists(target)) {
128+
return 1;
129+
}
130+
}
131+
return 0;
132+
}
133+
134+
template <typename value_type>
135+
static int write_file(
136+
const fs::path &path, const value_type &value,
137+
bool overwrite = false
138+
) {
139+
std::ofstream file(
140+
path,
141+
overwrite ? std::ofstream::trunc : std::ofstream::app
142+
);
143+
if (!file.is_open()) {
144+
// TODO: error
145+
return 1;
146+
}
147+
file << value << std::endl;
148+
file.close();
149+
return 0;
150+
}
151+
152+
template <typename value_type>
153+
static value_type read_file(const fs::path &path) {
154+
std::ifstream file(path);
155+
if (!file.is_open()) {
156+
// TODO: error
157+
return value_type();
158+
}
159+
value_type value;
160+
file >> value;
161+
file.close();
162+
return value;
163+
}
164+
165+
template <typename value_type>
166+
static std::vector<value_type> read_file_array(const fs::path &path) {
167+
std::ifstream file(path);
168+
if (!file.is_open()) {
169+
// TODO: error
170+
return std::vector<value_type>();
171+
}
172+
value_type temp;
173+
std::vector<value_type> value;
174+
while (!file.eof()) {
175+
file >> temp;
176+
value.push_back(temp);
177+
}
178+
return value;
179+
}
180+
181+
template <typename value_type>
182+
int hoj::write_cgroup_property(
183+
const hoj::cgroup_info &info, const std::string &controller,
184+
const std::string &property, const value_type &value, bool overwrite
185+
) {
186+
return write_file(
187+
get_cgroup_path(controller) / info.name / property,
188+
value, overwrite
189+
);
190+
}
191+
192+
template int hoj::write_cgroup_property<std::int32_t>(
193+
const hoj::cgroup_info &info, const std::string &controller,
194+
const std::string &property, const std::int32_t &value, bool overwrite
195+
);
196+
197+
template int hoj::write_cgroup_property<std::int64_t>(
198+
const hoj::cgroup_info &info, const std::string &controller,
199+
const std::string &property, const std::int64_t &value, bool overwrite
200+
);
201+
202+
template int hoj::write_cgroup_property<std::string>(
203+
const hoj::cgroup_info &info, const std::string &controller,
204+
const std::string &property, const std::string &value, bool overwrite
205+
);
206+
207+
template <typename value_type>
208+
value_type hoj::read_cgroup_property(
209+
const hoj::cgroup_info &info, const std::string &controller,
210+
const std::string &property
211+
) {
212+
return read_file<value_type>(
213+
get_cgroup_path(controller) / info.name / property
214+
);
215+
}
216+
217+
template std::int32_t hoj::read_cgroup_property<std::int32_t>(
218+
const hoj::cgroup_info &info, const std::string &controller,
219+
const std::string &property
220+
);
221+
222+
template std::int64_t hoj::read_cgroup_property<std::int64_t>(
223+
const hoj::cgroup_info &info, const std::string &controller,
224+
const std::string &property
225+
);

src/cgroup.h

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
This file is part of the Hydrogen OJ Judger.
3+
4+
This program is free software: you can redistribute it and/or modify
5+
it under the terms of the GNU Affero General Public License as published
6+
by the Free Software Foundation, either version 3 of the License, or
7+
(at your option) any later version.
8+
9+
This program is distributed in the hope that it will be useful,
10+
but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
GNU Affero General Public License for more details.
13+
14+
You should have received a copy of the GNU Affero General Public License
15+
along with this program. If not, see <https://www.gnu.org/licenses/>.
16+
*/
17+
18+
/* Copyright (C) 2020-2021 Alex Cui */
19+
20+
#ifndef _HOJ_JUDGER_CGROUP_H_
21+
#define _HOJ_JUDGER_CGROUP_H_
22+
23+
#include <cstdint>
24+
#include <string>
25+
#include <vector>
26+
27+
namespace hoj {
28+
struct cgroup_info {
29+
std::string name;
30+
std::vector<std::string> controller;
31+
};
32+
33+
int init_cgroup();
34+
bool cgroup_initialized();
35+
int create_cgroup(const cgroup_info &info);
36+
int remove_cgroup(const cgroup_info &info);
37+
int check_cgroup(const cgroup_info &info);
38+
39+
// Only for std::int64_t, std::string
40+
template <typename value_type>
41+
int write_cgroup_property(
42+
const cgroup_info &info, const std::string &controller,
43+
const std::string &property, const value_type &value,
44+
bool overwrite = true
45+
);
46+
47+
// Only for std::int64_t, std::string
48+
template <typename value_type>
49+
value_type read_cgroup_property(
50+
const cgroup_info &info, const std::string &controller,
51+
const std::string &property
52+
);
53+
}
54+
55+
#endif // _HOJ_JUDGER_CGROUP_H_

src/main.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,9 @@ int main(int argc, char *argv[]) {
9696
int max_compile_space = 262144;
9797

9898
std::string compile = hoj::format(compile_config.as<std::string>(), data);
99+
99100
std::cout << "Compile: " << compile << std::endl;
101+
100102
hoj::resource_usage usage;
101103
int compile_status = hoj::compile(usage, compile, compile_log_path, max_compile_time, max_compile_space);
102104

0 commit comments

Comments
 (0)