4
4
"context"
5
5
"io"
6
6
"strconv"
7
+ "time"
7
8
8
- // "log"
9
+ "log"
9
10
"path/filepath"
10
11
11
12
dockertypes "github.com/docker/docker/api/types"
@@ -15,8 +16,8 @@ import (
15
16
"github.com/pkg/errors"
16
17
)
17
18
18
- // Memory Limit of a G++ Process
19
19
const CompilationMemoryLimit = 100 * 1024 * 1024
20
+ const CompilationTimeLimit = 10 * time .Second
20
21
21
22
// it is required that the docker image is built before the program runs
22
23
const imageCompile = "markhuang1212/code-grader/runtime-compile:latest"
@@ -25,12 +26,15 @@ const imageCompile = "markhuang1212/code-grader/runtime-compile:latest"
25
26
// executable on success
26
27
func CompileUserCode (ctx context.Context , gr types.GradeRequest ) ([]byte , error ) {
27
28
29
+ ctxdl , cancel := context .WithTimeout (ctx , CompilationTimeLimit )
30
+ defer cancel ()
31
+
28
32
cli , err := client .NewClientWithOpts (client .FromEnv , client .WithAPIVersionNegotiation ())
29
33
if err != nil {
30
34
return nil , errors .WithMessage (err , "cannot create docker client" )
31
35
}
32
36
33
- resp , err := cli .ContainerCreate (ctx , & container.Config {
37
+ resp , err := cli .ContainerCreate (ctxdl , & container.Config {
34
38
Image : imageCompile ,
35
39
Env : []string {
36
40
"TEST_CASE_DIR=" + filepath .Join ("/code-grader/testcases" , gr .TestCaseName ),
@@ -49,7 +53,7 @@ func CompileUserCode(ctx context.Context, gr types.GradeRequest) ([]byte, error)
49
53
return nil , errors .Wrap (ErrInternalError , "cannot create container" )
50
54
}
51
55
52
- hjresp , err := cli .ContainerAttach (ctx , resp .ID , dockertypes.ContainerAttachOptions {
56
+ hjresp , err := cli .ContainerAttach (ctxdl , resp .ID , dockertypes.ContainerAttachOptions {
53
57
Stdin : true ,
54
58
Stream : true ,
55
59
})
@@ -58,21 +62,21 @@ func CompileUserCode(ctx context.Context, gr types.GradeRequest) ([]byte, error)
58
62
return nil , errors .Wrap (ErrInternalError , "cannot attach container" )
59
63
}
60
64
61
- statusCh , errCh := cli .ContainerWait (ctx , resp .ID , container .WaitConditionNextExit )
65
+ statusCh , errCh := cli .ContainerWait (ctxdl , resp .ID , container .WaitConditionNextExit )
62
66
63
- err = cli .ContainerStart (ctx , resp .ID , dockertypes.ContainerStartOptions {})
67
+ err = cli .ContainerStart (ctxdl , resp .ID , dockertypes.ContainerStartOptions {})
64
68
if err != nil {
65
69
return nil , errors .Wrap (ErrInternalError , "cannot start container" )
66
70
}
67
71
68
72
defer func () {
69
- // err := cli.ContainerRemove(ctx , resp.ID, dockertypes.ContainerRemoveOptions{
70
- // Force: true,
71
- // })
72
- // if err != nil {
73
- // log.Fatal ("cannot kill and remove container")
74
- // panic(err)
75
- // }
73
+ err := cli .ContainerRemove (ctxdl , resp .ID , dockertypes.ContainerRemoveOptions {
74
+ Force : true ,
75
+ })
76
+ if err != nil {
77
+ log .Panicln ("cannot kill and remove container" )
78
+ panic (err )
79
+ }
76
80
}()
77
81
78
82
userCodeLength := len (gr .UserCode )
@@ -88,7 +92,7 @@ func CompileUserCode(ctx context.Context, gr types.GradeRequest) ([]byte, error)
88
92
case status := <- statusCh :
89
93
switch status .StatusCode {
90
94
case 0 :
91
- stdout , err := cli .ContainerLogs (ctx , resp .ID , dockertypes.ContainerLogsOptions {
95
+ stdout , err := cli .ContainerLogs (ctxdl , resp .ID , dockertypes.ContainerLogsOptions {
92
96
ShowStdout : true ,
93
97
ShowStderr : false ,
94
98
})
@@ -98,7 +102,7 @@ func CompileUserCode(ctx context.Context, gr types.GradeRequest) ([]byte, error)
98
102
result , _ := io .ReadAll (stdout )
99
103
return result , nil
100
104
case 1 :
101
- stderr , err := cli .ContainerLogs (ctx , resp .ID , dockertypes.ContainerLogsOptions {
105
+ stderr , err := cli .ContainerLogs (ctxdl , resp .ID , dockertypes.ContainerLogsOptions {
102
106
ShowStderr : true ,
103
107
ShowStdout : false ,
104
108
})
0 commit comments