9
9
"os"
10
10
"os/exec"
11
11
"runtime"
12
- "slices"
13
12
"strconv"
14
13
"strings"
15
14
"syscall"
@@ -18,47 +17,57 @@ import (
18
17
"golang.org/x/xerrors"
19
18
)
20
19
20
+ // unset is set to an invalid value for nice and oom scores.
21
+ const unset = - 2000
22
+
21
23
// CLI runs the agent-exec command. It should only be called by the cli package.
22
- func CLI (args [] string , environ [] string ) error {
24
+ func CLI () error {
23
25
// We lock the OS thread here to avoid a race conditino where the nice priority
24
26
// we get is on a different thread from the one we set it on.
25
27
runtime .LockOSThread ()
26
28
27
- nice := flag .Int (niceArg , 0 , "" )
28
- oom := flag .Int (oomArg , 0 , "" )
29
+ var (
30
+ fs = flag .NewFlagSet ("agent-exec" , flag .ExitOnError )
31
+ nice = fs .Int ("coder-nice" , unset , "" )
32
+ oom = fs .Int ("coder-oom" , unset , "" )
33
+ )
34
+
35
+ if len (os .Args ) < 3 {
36
+ return xerrors .Errorf ("malformed command %+v" , os .Args )
37
+ }
29
38
30
- flag .Parse ()
39
+ // Parse everything after "coder agent-exec".
40
+ err := fs .Parse (os .Args [2 :])
41
+ if err != nil {
42
+ return xerrors .Errorf ("parse flags: %w" , err )
43
+ }
31
44
32
45
if runtime .GOOS != "linux" {
33
46
return xerrors .Errorf ("agent-exec is only supported on Linux" )
34
47
}
35
48
36
- if len (args ) < 2 {
37
- return xerrors .Errorf ("malformed command %q" , args )
49
+ // Get everything after "coder agent-exec --"
50
+ args := execArgs (os .Args )
51
+ if len (args ) == 0 {
52
+ return xerrors .Errorf ("no exec command provided %+v" , os .Args )
38
53
}
39
54
40
- // Slice off 'coder agent-exec'
41
- args = args [2 :]
42
-
43
55
pid := os .Getpid ()
44
56
45
- var err error
46
- if nice == nil {
57
+ if * nice == unset {
47
58
// If an explicit nice score isn't set, we use the default.
48
- n , err : = defaultNiceScore ()
59
+ * nice , err = defaultNiceScore ()
49
60
if err != nil {
50
61
return xerrors .Errorf ("get default nice score: %w" , err )
51
62
}
52
- nice = & n
53
63
}
54
64
55
- if oom == nil {
65
+ if * oom == unset {
56
66
// If an explicit oom score isn't set, we use the default.
57
- o , err : = defaultOOMScore ()
67
+ * oom , err = defaultOOMScore ()
58
68
if err != nil {
59
69
return xerrors .Errorf ("get default oom score: %w" , err )
60
70
}
61
- oom = & o
62
71
}
63
72
64
73
err = unix .Setpriority (unix .PRIO_PROCESS , 0 , * nice )
@@ -76,12 +85,7 @@ func CLI(args []string, environ []string) error {
76
85
return xerrors .Errorf ("look path: %w" , err )
77
86
}
78
87
79
- // Remove environments variables specifically set for the agent-exec command.
80
- env := slices .DeleteFunc (environ , func (env string ) bool {
81
- return strings .HasPrefix (env , EnvProcOOMScore ) || strings .HasPrefix (env , EnvProcNiceScore )
82
- })
83
-
84
- return syscall .Exec (path , args , env )
88
+ return syscall .Exec (path , args , os .Environ ())
85
89
}
86
90
87
91
func defaultNiceScore () (int , error ) {
@@ -133,3 +137,13 @@ func oomScoreAdj(pid int) (int, error) {
133
137
func writeOOMScoreAdj (pid int , score int ) error {
134
138
return os .WriteFile (fmt .Sprintf ("/proc/%d/oom_score_adj" , pid ), []byte (fmt .Sprintf ("%d" , score )), 0o600 )
135
139
}
140
+
141
+ // execArgs returns the arguments to pass to syscall.Exec after the "--" delimiter.
142
+ func execArgs (args []string ) []string {
143
+ for i , arg := range args {
144
+ if arg == "--" {
145
+ return args [i + 1 :]
146
+ }
147
+ }
148
+ return nil
149
+ }
0 commit comments