Skip to content

Commit 1f6b55f

Browse files
committed
add default timeout for test proc
1 parent f25a1bd commit 1f6b55f

File tree

7 files changed

+46
-35
lines changed

7 files changed

+46
-35
lines changed

.gitignore

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ __pycache__
66
docker_deploy
77
migrations
88
onl.db
9-
data/log
9+
data

conf/views.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,8 @@ def post(self, request):
190190

191191
class LanguagesAPI(APIView):
192192
def get(self, request):
193-
return self.success({"languages": SysOptions.languages, "spj_languages": SysOptions.spj_languages})
193+
return self.success({"languages": SysOptions.languages,
194+
"spj_languages": SysOptions.spj_languages})
194195

195196

196197
class TestCasePruneAPI(APIView):

contest/models.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,11 @@ class Contest(models.Model):
1717
# show real time rank or cached rank
1818
password = models.TextField(null=True)
1919
# enum of ContestRuleType
20-
start_time = models.DateTimeField(timezone.now())
20+
start_time = models.DateTimeField(default=timezone.now())
2121
end_time = models.DateTimeField(null=True)
2222
create_time = models.DateTimeField(auto_now_add=True)
2323
last_update_time = models.DateTimeField(auto_now=True)
2424
created_by = models.ForeignKey(User, on_delete=models.CASCADE)
25-
# 是否可见 false的话相当于删除
2625
visible = models.BooleanField(default=True)
2726
contest_admin = models.JSONField(default=list)
2827
allowed_ip_ranges = JSONField(default=list)
@@ -62,4 +61,4 @@ class ContestAnnouncement(models.Model):
6261

6362
class Meta:
6463
db_table = "contest_announcement"
65-
ordering = ("-create_time",)
64+
ordering = ("-create_time",)

judge/testing.py

+22-10
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@
1818
TESTCASE_NAME = "testcases.json"
1919
TESTER_NAME = "tester"
2020

21+
class TestResult:
22+
Succeed = 0
23+
Error = 1
24+
Timeout = 2
25+
2126
def create_new_problem_from_template(new_problem_id: str, old_problem_id: str):
2227
old_path = PathManager.problem_dir(old_problem_id)
2328
new_path = PathManager.problem_dir(new_problem_id)
@@ -41,14 +46,20 @@ def make_file_executable(file_path):
4146
return False
4247

4348

44-
def run_command_with_sudo(command):
49+
def run_command_with_timeout(command: list, timeout: float) -> int:
4550
try:
4651
# Use the 'sudo' command to execute the given command with elevated privileges.
47-
result = subprocess.run(['sudo'] + command, capture_output=True, text=True, check=True)
48-
return result
52+
result = subprocess.run(['sudo'] + command, capture_output=True, text=True, check=True, timeout=timeout)
53+
print("Command output:")
54+
print(result.stdout)
55+
return TestResult.Succeed
56+
except subprocess.TimeoutExpired:
57+
print('program timeout')
58+
return TestResult.Timeout
4959
except subprocess.CalledProcessError as e:
60+
print("Command execution failed.")
5061
print(f"Error: {e}")
51-
return None
62+
return TestResult.Error
5263

5364

5465
class PathManager:
@@ -165,12 +176,13 @@ def judge(self):
165176
if not exists(tester_path):
166177
raise Exception("running submission: tester {} not exists".format(tester_path))
167178
print(f"running {tester_path}")
168-
result = run_command_with_sudo([tester_path, "--log", "--json"])
169-
if result:
170-
print("Command output:")
171-
print(result.stdout)
172-
else:
173-
print("Command execution failed.")
179+
res = run_command_with_timeout([tester_path, "--log", "--json"], 1)
180+
if res == TestResult.Timeout:
181+
self.sub.result = JudgeStatus.PROGRAM_TIMEOUT
182+
self.sub.save()
183+
return
184+
elif res == TestResult.Error:
185+
raise Exception("Running test proc has some problem")
174186

175187
log_path = join(self.sub_dirpath, 'logs')
176188
if not exists(log_path):

run.sh

+3
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ elif [[ $cmd == "clean" ]]; then
1616
find . -type d -name 'migrations' -not -path './venv/*' | xargs rm -r;
1717
rm onl.db
1818
elif [[ $cmd == "rebuild" ]]; then
19+
rm -rf ./data/zips
20+
rm -rf ./data/problems
21+
rm -rf ./data/submissions
1922
find . -type d -name 'migrations' -not -path './venv/*' | xargs rm -r;
2023
rm onl.db
2124
for app in "${apps[@]}"; do

submission/models.py

+15-7
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,13 @@
99

1010

1111
class JudgeStatus:
12-
PENDING = 0
13-
JUDGING = 1
12+
PENDING = 0
13+
JUDGING = 1
1414
SYSTEM_ERROR = 2
15-
ALL_PASSED = 3
16-
SOME_PASSED = 4
17-
ALL_FAILED = 5
15+
ALL_PASSED = 3
16+
SOME_PASSED = 4
17+
ALL_FAILED = 5
18+
PROGRAM_TIMEOUT = 6
1819

1920

2021
class Submission(models.Model):
@@ -35,7 +36,12 @@ class Submission(models.Model):
3536
ip = models.TextField(null=True)
3637

3738
def check_user_permission(self, user, check_share=True):
38-
if self.user_id == user.id or user.is_super_admin() or user.can_mgmt_all_problem() or self.problem.created_by_id == user.id:
39+
if (
40+
self.user_id == user.id
41+
or user.is_super_admin()
42+
or user.can_mgmt_all_problem()
43+
or self.problem.created_by_id == user.id
44+
):
3945
return True
4046

4147
if check_share:
@@ -46,7 +52,9 @@ def check_user_permission(self, user, check_share=True):
4652
return False
4753

4854
def modify_permission(self, user, check_share=True):
49-
if user.is_super_admin() or (user.is_admin_role() and user.id in self.problem.contest.contest_admin):
55+
if user.is_super_admin() or (
56+
user.is_admin_role() and user.id in self.problem.contest.contest_admin
57+
):
5058
return True
5159
return False
5260

submission/views/user.py

+1-13
Original file line numberDiff line numberDiff line change
@@ -147,14 +147,11 @@ def get(self, request):
147147
if not submission.check_user_permission(request.user):
148148
return self.error("No permission for this submission")
149149

150-
if submission.result in [JudgeStatus.PENDING, JudgeStatus.JUDGING]:
151-
# update_submission_status(submission)
152-
pass
153-
154150
submission_data = SubmissionSafeModelSerializer(submission).data
155151
submission_data["can_unshare"] = submission.check_user_permission(
156152
request.user, check_share=False
157153
)
154+
submission_data["code_names"] = submission.problem.code_names
158155
return self.success(submission_data)
159156

160157
@validate_serializer(ShareSubmissionSerializer)
@@ -197,11 +194,6 @@ def get(self, request):
197194
user_id=request.user.id
198195
)
199196

200-
for submission in submissions:
201-
if submission.result in [JudgeStatus.PENDING, JudgeStatus.JUDGING]:
202-
# update_submission_status(submission)
203-
pass
204-
205197
problem_id = request.GET.get("problem_id")
206198
result = request.GET.get("result")
207199
if problem_id:
@@ -248,10 +240,6 @@ def get(self, request):
248240
submissions = Submission.objects.filter(contest_id=contest_id).filter(
249241
user_id=request.user.id
250242
)
251-
for submission in submissions:
252-
if submission.result in [JudgeStatus.PENDING, JudgeStatus.JUDGING]:
253-
# update_submission_status(submission)
254-
pass
255243

256244
problem_id = request.GET.get("problem_id")
257245
result = request.GET.get("result")

0 commit comments

Comments
 (0)