mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: integrate new agentexec pkg (#15609)
- Integrates the `agentexec` pkg into the agent and removes the legacy system of iterating over the process tree. It adds some linting rules to hopefully catch future improper uses of `exec.Command` in the package.
This commit is contained in:
@@ -23,7 +23,8 @@ const unset = -2000
|
||||
// CLI runs the agent-exec command. It should only be called by the cli package.
|
||||
func CLI() error {
|
||||
// We lock the OS thread here to avoid a race condition where the nice priority
|
||||
// we get is on a different thread from the one we set it on.
|
||||
// we set gets applied to a different thread than the one we exec the provided
|
||||
// command on.
|
||||
runtime.LockOSThread()
|
||||
// Nop on success but we do it anyway in case of an error.
|
||||
defer runtime.UnlockOSThread()
|
||||
@@ -68,12 +69,18 @@ func CLI() error {
|
||||
|
||||
err = unix.Setpriority(unix.PRIO_PROCESS, 0, *nice)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("set nice score: %w", err)
|
||||
// We alert the user instead of failing the command since it can be difficult to debug
|
||||
// for a template admin otherwise. It's quite possible (and easy) to set an
|
||||
// inappriopriate value for niceness.
|
||||
printfStdErr("failed to adjust niceness to %q: %v", *nice, err)
|
||||
}
|
||||
|
||||
err = writeOOMScoreAdj(*oom)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("set oom score: %w", err)
|
||||
// We alert the user instead of failing the command since it can be difficult to debug
|
||||
// for a template admin otherwise. It's quite possible (and easy) to set an
|
||||
// inappriopriate value for oom_score_adj.
|
||||
printfStdErr("failed to adjust oom score to %q: %v", *nice, err)
|
||||
}
|
||||
|
||||
path, err := exec.LookPath(args[0])
|
||||
@@ -143,3 +150,7 @@ func execArgs(args []string) []string {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func printfStdErr(format string, a ...any) {
|
||||
_, _ = fmt.Fprintf(os.Stderr, "coder-agent: %s\n", fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
+26
-4
@@ -10,6 +10,8 @@ import (
|
||||
"strconv"
|
||||
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/coder/coder/v2/pty"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -25,19 +27,39 @@ const (
|
||||
// is returned. All instances of exec.Cmd should flow through this function to ensure
|
||||
// proper resource constraints are applied to the child process.
|
||||
func CommandContext(ctx context.Context, cmd string, args ...string) (*exec.Cmd, error) {
|
||||
cmd, args, err := agentExecCmd(cmd, args...)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("agent exec cmd: %w", err)
|
||||
}
|
||||
return exec.CommandContext(ctx, cmd, args...), nil
|
||||
}
|
||||
|
||||
// PTYCommandContext returns an pty.Cmd that calls "coder agent-exec" prior to exec'ing
|
||||
// the provided command if CODER_PROC_PRIO_MGMT is set, otherwise a normal pty.Cmd
|
||||
// is returned. All instances of pty.Cmd should flow through this function to ensure
|
||||
// proper resource constraints are applied to the child process.
|
||||
func PTYCommandContext(ctx context.Context, cmd string, args ...string) (*pty.Cmd, error) {
|
||||
cmd, args, err := agentExecCmd(cmd, args...)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("agent exec cmd: %w", err)
|
||||
}
|
||||
return pty.CommandContext(ctx, cmd, args...), nil
|
||||
}
|
||||
|
||||
func agentExecCmd(cmd string, args ...string) (string, []string, error) {
|
||||
_, enabled := os.LookupEnv(EnvProcPrioMgmt)
|
||||
if runtime.GOOS != "linux" || !enabled {
|
||||
return exec.CommandContext(ctx, cmd, args...), nil
|
||||
return cmd, args, nil
|
||||
}
|
||||
|
||||
executable, err := os.Executable()
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("get executable: %w", err)
|
||||
return "", nil, xerrors.Errorf("get executable: %w", err)
|
||||
}
|
||||
|
||||
bin, err := filepath.EvalSymlinks(executable)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("eval symlinks: %w", err)
|
||||
return "", nil, xerrors.Errorf("eval symlinks: %w", err)
|
||||
}
|
||||
|
||||
execArgs := []string{"agent-exec"}
|
||||
@@ -51,7 +73,7 @@ func CommandContext(ctx context.Context, cmd string, args ...string) (*exec.Cmd,
|
||||
execArgs = append(execArgs, "--", cmd)
|
||||
execArgs = append(execArgs, args...)
|
||||
|
||||
return exec.CommandContext(ctx, bin, execArgs...), nil
|
||||
return bin, execArgs, nil
|
||||
}
|
||||
|
||||
// envValInt searches for a key in a list of environment variables and parses it to an int.
|
||||
|
||||
Reference in New Issue
Block a user