@@ -12,27 +12,30 @@ import (
12
12
"github.com/docker/docker/api/types/container"
13
13
"github.com/docker/docker/client"
14
14
"github.com/docker/docker/pkg/stdcopy"
15
- "github.com/markhuang1212/code-grader/types"
15
+ "github.com/markhuang1212/code-grader/backend/ types"
16
16
"github.com/pkg/errors"
17
17
)
18
18
19
19
const imageExec = "markhuang1212/code-grader/runtime-exec:latest"
20
20
21
- func exec_user_code (ctx context.Context , gr types.GradeRequest ) ([]byte , error ) {
21
+ func ExecUserCode (ctx context.Context , gr types.GradeRequest ) ([]byte , error ) {
22
22
23
23
var testCase types.TestCaseOptions
24
24
25
25
testCaseJson , err := os .ReadFile (filepath .Join (AppRoot , "testcases" , gr .TestCaseName , "testcase.json" ))
26
26
if err != nil {
27
- return nil , errors .Wrap (InternalError , "cannot open testcase.json" )
27
+ return nil , errors .Wrap (ErrInternalError , "cannot open testcase.json" )
28
28
}
29
29
30
30
err = json .Unmarshal (testCaseJson , & testCase )
31
31
if err != nil {
32
- return nil , errors .Wrap (InternalError , "cannot parse testcase.json" )
32
+ return nil , errors .Wrap (ErrInternalError , "cannot parse testcase.json" )
33
33
}
34
34
35
35
cli , err := client .NewClientWithOpts (client .FromEnv , client .WithAPIVersionNegotiation ())
36
+ if err != nil {
37
+ return nil , errors .Wrap (ErrInternalError , "cannot create docker client" )
38
+ }
36
39
37
40
resp , err := cli .ContainerCreate (ctx , & container.Config {
38
41
Image : imageExec ,
@@ -49,7 +52,7 @@ func exec_user_code(ctx context.Context, gr types.GradeRequest) ([]byte, error)
49
52
}, nil , nil , "" )
50
53
51
54
if err != nil {
52
- return nil , errors .Wrap (InternalError , "cannot create container" )
55
+ return nil , errors .Wrap (ErrInternalError , "cannot create container" )
53
56
}
54
57
55
58
hjresp , err := cli .ContainerAttach (ctx , resp .ID , dockertypes.ContainerAttachOptions {
@@ -60,7 +63,7 @@ func exec_user_code(ctx context.Context, gr types.GradeRequest) ([]byte, error)
60
63
})
61
64
62
65
if err != nil {
63
- return nil , errors .Wrap (InternalError , "cannot attach container" )
66
+ return nil , errors .Wrap (ErrInternalError , "cannot attach container" )
64
67
}
65
68
66
69
ctxdl , cancel := context .WithTimeout (ctx , time .Second * time .Duration (testCase .RuntimeOptions .RuntimeLimit ))
@@ -70,9 +73,14 @@ func exec_user_code(ctx context.Context, gr types.GradeRequest) ([]byte, error)
70
73
71
74
err = cli .ContainerStart (ctxdl , resp .ID , dockertypes.ContainerStartOptions {})
72
75
if err != nil {
73
- return nil , errors .Wrap (InternalError , "cannot start container" )
76
+ return nil , errors .Wrap (ErrInternalError , "cannot start container" )
74
77
}
75
78
79
+ defer cli .ContainerRemove (ctx , resp .ID , dockertypes.ContainerRemoveOptions {
80
+ Force : true ,
81
+ })
82
+ defer cli .ContainerStop (ctx , resp .ID , nil )
83
+
76
84
outR , outW := io .Pipe ()
77
85
errR , errW := io .Pipe ()
78
86
hjresp .Conn .Write ([]byte (gr .UserCode ))
@@ -84,28 +92,28 @@ func exec_user_code(ctx context.Context, gr types.GradeRequest) ([]byte, error)
84
92
select {
85
93
case status := <- statusCh :
86
94
switch status .StatusCode {
87
- case 0 :
95
+ case 0 : // success
88
96
result , err := io .ReadAll (outR )
89
97
if err != nil {
90
- return nil , errors .Wrap (InternalError , "error reading outR" )
98
+ return nil , errors .Wrap (ErrInternalError , "error reading outR" )
91
99
}
92
100
return result , nil
93
- case 1 :
101
+ case 1 : // wrong result
94
102
result , err := io .ReadAll (errR )
95
103
if err != nil {
96
- return nil , errors .Wrap (InternalError , "error reading errR" )
104
+ return nil , errors .Wrap (ErrInternalError , "error reading errR" )
97
105
}
98
- return result , CompilationError
99
- case 2 :
100
- return nil , InternalError
106
+ return result , ErrCompilationError
107
+ case 2 : // internal error
108
+ return nil , ErrInternalError
101
109
default :
102
- return nil , InternalError
110
+ return nil , ErrInternalError
103
111
}
104
112
case err := <- errCh :
105
113
if errors .Is (err , context .DeadlineExceeded ) {
106
- return nil , TimeLimitExceed
114
+ return nil , ErrTimeLimitExceed
107
115
}
108
- return nil , errors .Wrap (InternalError , "error waiting container" )
116
+ return nil , errors .Wrap (ErrInternalError , "error waiting container" )
109
117
}
110
118
111
119
}
0 commit comments