Skip to content

Commit

Permalink
sweet/benchmark/internal/cgroups: test system-run functionality
Browse files Browse the repository at this point in the history
Add a rudimentary test for starting a user scope with systemd-run. If it
doesn't work, then skip the wrapper.

For golang/go#54760.

Change-Id: I7b742b49ae453b8d485d7d0c008b9fb9148c37ac
Reviewed-on: https://go-review.googlesource.com/c/benchmarks/+/426238
Run-TryBot: Michael Pratt <mpratt@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
  • Loading branch information
prattmic committed Aug 30, 2022
1 parent e377fc9 commit 2a5261f
Showing 1 changed file with 55 additions and 6 deletions.
61 changes: 55 additions & 6 deletions sweet/benchmarks/internal/cgroups/cgroups.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,54 @@ import (
"path/filepath"
"strconv"
"strings"
"sync"
"time"
)

func findSystemdRun() (string, error) {
bin, err := exec.LookPath("systemd-run")
if errors.Is(err, exec.ErrNotFound) {
return "", fmt.Errorf("systemd-run binary not found")
} else if err != nil {
return "", fmt.Errorf("error looking for systemd-run: %w", err)
}

scope := fmt.Sprintf("systemd-run-test-%d.scope", time.Now().UnixNano())

cmd := exec.Command(bin, "--user", "--scope", "--unit", scope, "/bin/true")
sout, serr := cmd.CombinedOutput()
if serr == nil {
// It works!
return bin, nil
}

var context strings.Builder
fmt.Fprintf(&context, "\noutput: %s", string(sout))

// Failed. systemd-run probably just said to look at journalctl;
// collect that additional context.
cmd = exec.Command("journalctl", "--catalog", "--user", "--unit", scope)
jout, jerr := cmd.CombinedOutput()
if jerr != nil {
fmt.Fprintf(&context, "\njournalctl error: %v\noutout: %s", jerr, string(jout))
} else {
fmt.Fprintf(&context, "\njournalctl output: %s", string(jout))
}

// Attempt to cleanup unit.
cmd = exec.Command("systemctl", "--user", "reset-failed", scope)
scout, scerr := cmd.CombinedOutput()
if scerr != nil {
fmt.Fprintf(&context, "\nsystemctl cleanup error: %v\noutput: %s", scerr, string(scout))
}

return "", fmt.Errorf("system-run failed: %w%s", serr, context.String())
}

var (
systemdOnce sync.Once
systemdRunPath string
systemdRunError error
)

type Cmd struct {
Expand All @@ -25,13 +73,13 @@ type Cmd struct {
func WrapCommand(cmd *exec.Cmd, scope string) (*Cmd, error) {
wrapped := Cmd{Cmd: *cmd}

// TODO(mknyszek): Maybe make a more stringent check?
systemdRunPath, err := exec.LookPath("systemd-run")
if errors.Is(err, exec.ErrNotFound) {
fmt.Fprintln(os.Stderr, "# warning: systemd-run not available, skipping...")
systemdOnce.Do(func() {
systemdRunPath, systemdRunError = findSystemdRun()
})

if systemdRunError != nil {
fmt.Fprintf(os.Stderr, "# warning: systemd-run not available: %v\n# skipping cgroup wrapper...\n", systemdRunError)
return &wrapped, nil
} else if err != nil {
return nil, err
}

u, err := user.Current()
Expand Down Expand Up @@ -62,3 +110,4 @@ func (c *Cmd) RSSFunc() func() (uint64, error) {
return strconv.ParseUint(strings.TrimSpace(string(data)), 10, 64)
}
}

0 comments on commit 2a5261f

Please sign in to comment.