Skip to content

Commit 7c96dfb

Browse files
committed
Make execution timed
1 parent d02f9ec commit 7c96dfb

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
@@ -14,6 +14,7 @@ import (
1414
"path"
1515
"path/filepath"
1616
"strings"
17+
"time"
1718

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

2835
var (
@@ -59,6 +66,7 @@ type CaseDescription struct {
5966
OutputFile string
6067
WorkFile string
6168
CustomCase bool
69+
TimeLimit float64
6270
}
6371

6472
func getWorkFile(fileName string) string {
@@ -68,14 +76,15 @@ func getWorkFile(fileName string) string {
6876
}
6977

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

@@ -144,6 +153,8 @@ func getDisplayStatus(status int8) string {
144153
return yellow("SK")
145154
case WA:
146155
return red("WA")
156+
case TL:
157+
return red("TL") // TODO(Eroui): Add another color?
147158
}
148159
return "Unknown"
149160
}
@@ -181,6 +192,22 @@ func newJudgeReport() JudgeReport {
181192
return &ConsoleJudgeReport{Stats: []CaseStatus{}}
182193
}
183194

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

460497
for i, input := range egorMeta.Inputs {
461498
output := egorMeta.Outputs[i]
462-
caseDescription := NewCaseDescription(input, output)
499+
caseDescription := NewCaseDescription(input, output, egorMeta.TimeLimit)
463500
status := judge.RunTestCase(*caseDescription)
464501
report.Add(status, *caseDescription)
465502
}

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)