sbox: run commands using script for large commands
Linux has limit of 32 pages for a single argument. Sbox's method of handling commands as a single large string can run into this limitation. Write the large command to a script file and then execute that file. This better accommodates the large commands, and leaves a script in the temporary directory useful for manual inspection if necessary. Bug: 177070955 Bug: 174232579 Fixes: 202297224 Test: m Test: make particular target with very long command exceeding limit. Change-Id: Ia298fdfd7a759821c37f540deaf800026041e511
This commit is contained in:
parent
17acadbcb0
commit
0a5da7025e
1 changed files with 29 additions and 3 deletions
|
@ -164,7 +164,7 @@ func run() error {
|
||||||
if useSubDir {
|
if useSubDir {
|
||||||
localTempDir = filepath.Join(localTempDir, strconv.Itoa(i))
|
localTempDir = filepath.Join(localTempDir, strconv.Itoa(i))
|
||||||
}
|
}
|
||||||
depFile, err := runCommand(command, localTempDir)
|
depFile, err := runCommand(command, localTempDir, i)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Running the command failed, keep the temporary output directory around in
|
// Running the command failed, keep the temporary output directory around in
|
||||||
// case a user wants to inspect it for debugging purposes. Soong will delete
|
// case a user wants to inspect it for debugging purposes. Soong will delete
|
||||||
|
@ -194,6 +194,28 @@ func run() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// createCommandScript will create and return an exec.Cmd that runs rawCommand.
|
||||||
|
//
|
||||||
|
// rawCommand is executed via a script in the sandbox.
|
||||||
|
// tempDir is the temporary where the script is created.
|
||||||
|
// toDirInSandBox is the path containing the script in the sbox environment.
|
||||||
|
// toDirInSandBox is the path containing the script in the sbox environment.
|
||||||
|
// seed is a unique integer used to distinguish different scripts that might be at location.
|
||||||
|
//
|
||||||
|
// returns an exec.Cmd that can be ran from within sbox context if no error, or nil if error.
|
||||||
|
// caller must ensure script is cleaned up if function succeeds.
|
||||||
|
//
|
||||||
|
func createCommandScript(rawCommand string, tempDir, toDirInSandbox string, seed int) (*exec.Cmd, error) {
|
||||||
|
scriptName := fmt.Sprintf("sbox_command.%d.bash", seed)
|
||||||
|
scriptPathAndName := joinPath(tempDir, scriptName)
|
||||||
|
err := os.WriteFile(scriptPathAndName, []byte(rawCommand), 0644)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to write command %s... to %s",
|
||||||
|
rawCommand[0:40], scriptPathAndName)
|
||||||
|
}
|
||||||
|
return exec.Command("bash", joinPath(toDirInSandbox, filepath.Base(scriptName))), nil
|
||||||
|
}
|
||||||
|
|
||||||
// readManifest reads an sbox manifest from a textproto file.
|
// readManifest reads an sbox manifest from a textproto file.
|
||||||
func readManifest(file string) (*sbox_proto.Manifest, error) {
|
func readManifest(file string) (*sbox_proto.Manifest, error) {
|
||||||
manifestData, err := ioutil.ReadFile(file)
|
manifestData, err := ioutil.ReadFile(file)
|
||||||
|
@ -213,7 +235,7 @@ func readManifest(file string) (*sbox_proto.Manifest, error) {
|
||||||
|
|
||||||
// runCommand runs a single command from a manifest. If the command references the
|
// runCommand runs a single command from a manifest. If the command references the
|
||||||
// __SBOX_DEPFILE__ placeholder it returns the name of the depfile that was used.
|
// __SBOX_DEPFILE__ placeholder it returns the name of the depfile that was used.
|
||||||
func runCommand(command *sbox_proto.Command, tempDir string) (depFile string, err error) {
|
func runCommand(command *sbox_proto.Command, tempDir string, commandIndex int) (depFile string, err error) {
|
||||||
rawCommand := command.GetCommand()
|
rawCommand := command.GetCommand()
|
||||||
if rawCommand == "" {
|
if rawCommand == "" {
|
||||||
return "", fmt.Errorf("command is required")
|
return "", fmt.Errorf("command is required")
|
||||||
|
@ -255,7 +277,11 @@ func runCommand(command *sbox_proto.Command, tempDir string) (depFile string, er
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := exec.Command("bash", "-c", rawCommand)
|
cmd, err := createCommandScript(rawCommand, tempDir, pathToTempDirInSbox, commandIndex)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
buf := &bytes.Buffer{}
|
buf := &bytes.Buffer{}
|
||||||
cmd.Stdin = os.Stdin
|
cmd.Stdin = os.Stdin
|
||||||
cmd.Stdout = buf
|
cmd.Stdout = buf
|
||||||
|
|
Loading…
Reference in a new issue