@@ -2,9 +2,8 @@ package cmd
2
2
3
3
import (
4
4
"context"
5
- "fmt"
6
5
"io"
7
- "strconv "
6
+ "os "
8
7
"time"
9
8
10
9
"log"
@@ -18,9 +17,8 @@ import (
18
17
)
19
18
20
19
type CompileUserCodeResult struct {
21
- Ok bool
22
- Result []byte
23
- Msg string
20
+ Ok bool
21
+ Msg string
24
22
}
25
23
26
24
const CompilationMemoryLimit = 256 * 1024 * 1024
@@ -33,14 +31,19 @@ const imageCompile = "markhuang1212/code-grader/runtime-compile:latest"
33
31
34
32
// The function compiles user's code inside a docker container, and returns the
35
33
// executable on success
36
- func CompileUserCode (ctx context.Context , gr types.GradeRequest ) (* CompileUserCodeResult , error ) {
34
+ func CompileUserCode (ctx context.Context , gr types.GradeRequest , tmpDir string ) (* CompileUserCodeResult , error ) {
37
35
38
36
result := & CompileUserCodeResult {}
39
37
40
38
if ! IsTestcase (gr .TestCaseName ) {
41
39
return nil , types .ErrNoTestCase
42
40
}
43
41
42
+ err := os .WriteFile (filepath .Join (tmpDir , "code.txt" ), []byte (gr .UserCode ), 0666 )
43
+ if err != nil {
44
+ return nil , errors .Wrap (err , "cannot write code.txt" )
45
+ }
46
+
44
47
cli , err := client .NewClientWithOpts (client .FromEnv , client .WithAPIVersionNegotiation ())
45
48
if err != nil {
46
49
return nil , errors .WithMessage (err , "cannot create docker client" )
@@ -56,27 +59,19 @@ func CompileUserCode(ctx context.Context, gr types.GradeRequest) (*CompileUserCo
56
59
"CXX=g++" ,
57
60
"CXXFLAGS=-std=c++11" ,
58
61
},
59
- OpenStdin : true ,
60
62
}, & container.HostConfig {
63
+ Binds : []string {tmpDir + ":/data" },
61
64
NetworkMode : "none" ,
62
- Resources : container.Resources {
63
- // Memory: CompilationMemoryLimit,
65
+ Resources : container.Resources {
66
+ Memory : CompilationMemoryLimit ,
67
+ MemorySwap : CompilationMemoryLimit ,
64
68
},
65
69
}, nil , nil , "" )
66
70
67
71
if err != nil {
68
72
return nil , errors .Wrap (err , "cannot create container" )
69
73
}
70
74
71
- hjresp , err := cli .ContainerAttach (ctxdl , resp .ID , dockertypes.ContainerAttachOptions {
72
- Stdin : true ,
73
- Stream : true ,
74
- })
75
-
76
- if err != nil {
77
- return nil , errors .Wrap (err , "cannot attach container" )
78
- }
79
-
80
75
statusCh , errCh := cli .ContainerWait (ctxdl , resp .ID , container .WaitConditionNextExit )
81
76
82
77
err = cli .ContainerStart (ctxdl , resp .ID , dockertypes.ContainerStartOptions {})
@@ -94,35 +89,22 @@ func CompileUserCode(ctx context.Context, gr types.GradeRequest) (*CompileUserCo
94
89
}
95
90
}()
96
91
97
- userCodeLength := len (gr .UserCode )
98
- fmt .Fprintln (hjresp .Conn , strconv .Itoa (userCodeLength ))
99
- hjresp .Conn .Write ([]byte (gr .UserCode ))
100
- hjresp .Close ()
101
-
102
92
select {
103
93
case status := <- statusCh :
104
94
switch status .StatusCode {
105
95
case 0 :
106
- stdout , err := cli .ContainerLogs (ctxdl , resp .ID , dockertypes.ContainerLogsOptions {
107
- ShowStdout : true ,
108
- ShowStderr : false ,
109
- })
110
- if err != nil {
111
- return nil , errors .Wrap (err , "error reading stdout" )
112
- }
113
- program , _ := io .ReadAll (stdout )
114
96
result .Ok = true
115
- result .Result = program
97
+ result .Msg = "compilation success"
116
98
return result , nil
117
99
case 1 :
118
- stderr , err := cli .ContainerLogs (ctxdl , resp .ID , dockertypes.ContainerLogsOptions {
100
+ out , err := cli .ContainerLogs (ctxdl , resp .ID , dockertypes.ContainerLogsOptions {
119
101
ShowStderr : true ,
120
- ShowStdout : false ,
102
+ ShowStdout : true ,
121
103
})
122
104
if err != nil {
123
105
return nil , errors .Wrap (err , "error reading stdout" )
124
106
}
125
- errText , _ := io .ReadAll (stderr )
107
+ errText , _ := io .ReadAll (out )
126
108
result .Msg = string (errText )
127
109
result .Ok = false
128
110
return result , nil
0 commit comments