Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0c517bd9 authored by Yoshisato Yanagisawa's avatar Yoshisato Yanagisawa
Browse files

Fatal error on insufficient resource to use Goma in Soong UI.

As suggested in
https://android-review.googlesource.com/c/platform/build/soong/+/839293


I am moving some features in goma.mk to goma.go in Soong UI.

With this CL, let me implement ulimit check to Soong UI.

Test: export USE_GOMA=true
Test: launch aosp_arm-eng
Test: make
Test: the command succeeds if "ulimit -n" and "ulimit -u" are large enough.
Test: Otherwise, it shows error.  I confirmed both cases.
Change-Id: I5d7d5ed71f620302a0d635770d1a51a2baab51fd
Signed-off-by: default avatarYoshisato Yanagisawa <yyanagisawa@google.com>
parent 3a1fd8e0
Loading
Loading
Loading
Loading
+38 −7
Original line number Diff line number Diff line
@@ -15,34 +15,65 @@
package build

import (
	"errors"
	"fmt"
	"math"
	"path/filepath"
	"strconv"
	"strings"

	"android/soong/ui/metrics"
)

const gomaCtlScript = "goma_ctl.py"
const gomaLeastNProcs = 2500
const gomaLeastNFiles = 16000

var gomaCtlNotFound = errors.New("goma_ctl.py not found")
// ulimit returns ulimit result for |opt|.
// if the resource is unlimited, it returns math.MaxInt32 so that a caller do
// not need special handling of the returned value.
//
// Note that since go syscall package do not have RLIMIT_NPROC constant,
// we use bash ulimit instead.
func ulimitOrFatal(ctx Context, config Config, opt string) int {
	commandText := fmt.Sprintf("ulimit %s", opt)
	cmd := Command(ctx, config, commandText, "bash", "-c", commandText)
	output := strings.TrimRight(string(cmd.CombinedOutputOrFatal()), "\n")
	ctx.Verbose(output + "\n")
	ctx.Verbose("done\n")

	if output == "unlimited" {
		return math.MaxInt32
	}
	num, err := strconv.Atoi(output)
	if err != nil {
		ctx.Fatalf("ulimit returned unexpected value: %s: %v\n", opt, err)
	}
	return num
}

func startGoma(ctx Context, config Config) error {
func startGoma(ctx Context, config Config) {
	ctx.BeginTrace(metrics.RunSetupTool, "goma_ctl")
	defer ctx.EndTrace()

	if u := ulimitOrFatal(ctx, config, "-u"); u < gomaLeastNProcs {
		ctx.Fatalf("max user processes is insufficient: %d; want >= %d.\n", u, gomaLeastNProcs)
	}
	if n := ulimitOrFatal(ctx, config, "-n"); n < gomaLeastNFiles {
		ctx.Fatalf("max open files is insufficient: %d; want >= %d.\n", n, gomaLeastNFiles)
	}

	var gomaCtl string
	if gomaDir, ok := config.Environment().Get("GOMA_DIR"); ok {
		gomaCtl = filepath.Join(gomaDir, gomaCtlScript)
	} else if home, ok := config.Environment().Get("HOME"); ok {
		gomaCtl = filepath.Join(home, "goma", gomaCtlScript)
	} else {
		return gomaCtlNotFound
		ctx.Fatalln("goma_ctl.py not found")
	}

	cmd := Command(ctx, config, "goma_ctl.py ensure_start", gomaCtl, "ensure_start")

	if err := cmd.Run(); err != nil {
		ctx.Fatalf("goma_ctl.py ensure_start failed with: %v", err)
		ctx.Fatalf("goma_ctl.py ensure_start failed with: %v\n", err)
	}

	return nil
}