Skip to content

Commit 4bbe94c

Browse files
committed
Make execution timed
1 parent 6b52aa7 commit 4bbe94c

File tree

2 files changed

+42
-3
lines changed

2 files changed

+42
-3
lines changed

commands/run.go

+40-3
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"path"
1414
"path/filepath"
1515
"strings"
16+
"time"
1617

1718
"github.com/urfave/cli/v2"
1819
)
@@ -22,6 +23,12 @@ var (
2223
SK int8 = 1
2324
RE int8 = 2
2425
WA int8 = 3
26+
TL int8 = 4
27+
)
28+
29+
var (
30+
OK int8 = 0 // OK execution status
31+
TO int8 = 1 // Timed out status
2532
)
2633

2734
var (
@@ -58,6 +65,7 @@ type CaseDescription struct {
5865
OutputFile string
5966
WorkFile string
6067
CustomCase bool
68+
TimeLimit float64
6169
}
6270

6371
func getWorkFile(fileName string) string {
@@ -67,14 +75,15 @@ func getWorkFile(fileName string) string {
6775
}
6876

6977
// Creates a new CaseDescription from a pair of input and output IoFiles
70-
func NewCaseDescription(input, output config.IoFile) *CaseDescription {
78+
func NewCaseDescription(input, output config.IoFile, timeLimit float64) *CaseDescription {
7179
base, file := filepath.Split(input.Path)
7280
workFilePath := path.Join(base, getWorkFile(file))
7381
return &CaseDescription{
7482
InputFile: input.Path,
7583
OutputFile: output.Path,
7684
WorkFile: workFilePath,
7785
CustomCase: input.Custom,
86+
TimeLimit: timeLimit,
7887
}
7988
}
8089

@@ -143,6 +152,8 @@ func getDisplayStatus(status int8) string {
143152
return yellow("SK")
144153
case WA:
145154
return red("WA")
155+
case TL:
156+
return red("TL") // TODO(Eroui): Add another color?
146157
}
147158
return "Unknown"
148159
}
@@ -180,6 +191,22 @@ func newJudgeReport() JudgeReport {
180191
return &ConsoleJudgeReport{Stats: []CaseStatus{}}
181192
}
182193

194+
195+
func timedExecution(cmd *exec.Cmd, timeOut float64) (int8, error) {
196+
cmd.Start()
197+
done := make(chan error)
198+
go func() { done <- cmd.Wait() }()
199+
200+
timeout := time.After(time.Duration(timeOut) * time.Millisecond)
201+
select {
202+
case <- timeout:
203+
cmd.Process.Kill()
204+
return TO, nil
205+
case err := <-done:
206+
return OK, err
207+
}
208+
}
209+
183210
// Utility function to execute the given command that is associated with the given judge
184211
// the method returns the case status and the error (if any)
185212
func execute(judge Judge, desc CaseDescription, command string, args ...string) (CaseStatus, error) {
@@ -207,7 +234,17 @@ func execute(judge Judge, desc CaseDescription, command string, args ...string)
207234
cmd.Stdin = inputFile
208235
cmd.Stdout = outputFile
209236
cmd.Stderr = &stderrBuffer
210-
if err = cmd.Run(); err != nil {
237+
238+
status, err := timedExecution(cmd, desc.TimeLimit)
239+
if status == TO {
240+
return CaseStatus{
241+
Status: TL,
242+
CheckerError: nil,
243+
Stderr: stderrBuffer.String(),
244+
}, nil
245+
}
246+
247+
if err != nil {
211248
return CaseStatus{
212249
Status: RE,
213250
CheckerError: nil,
@@ -420,7 +457,7 @@ func RunAction(_ *cli.Context) error {
420457

421458
for i, input := range egorMeta.Inputs {
422459
output := egorMeta.Outputs[i]
423-
caseDescription := NewCaseDescription(input, output)
460+
caseDescription := NewCaseDescription(input, output, egorMeta.TimeLimit)
424461
status := judge.RunTestCase(*caseDescription)
425462
report.Add(status, *caseDescription)
426463
}

config/meta.go

+2
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ type EgorMeta struct {
4545
Inputs []IoFile
4646
Outputs []IoFile
4747
TaskFile string
48+
TimeLimit float64
4849
}
4950

5051
// Resolves the task file given the default language.
@@ -80,6 +81,7 @@ func NewEgorMeta(task Task, config Config) EgorMeta {
8081
Inputs: inputs,
8182
Outputs: outputs,
8283
TaskFile: taskFile,
84+
TimeLimit: task.TimeLimit,
8385
}
8486
}
8587

0 commit comments

Comments
 (0)