16347: Run a dedicated keepstore process for each container.
[arvados.git] / lib / crunchrun / background.go
index 4bb249380fd98b2e340bc4bd3bacb2b78d5f0a47..07f8f5b885d6dd2f7b87d7c16c75734880a9a7a0 100644 (file)
@@ -36,10 +36,10 @@ type procinfo struct {
 //
 // Stdout and stderr in the child process are sent to the systemd
 // journal using the systemd-cat program.
-func Detach(uuid string, prog string, args []string, stdout, stderr io.Writer) int {
-       return exitcode(stderr, detach(uuid, prog, args, stdout, stderr))
+func Detach(uuid string, prog string, args []string, stdin io.Reader, stdout, stderr io.Writer) int {
+       return exitcode(stderr, detach(uuid, prog, args, stdin, stdout))
 }
-func detach(uuid string, prog string, args []string, stdout, stderr io.Writer) error {
+func detach(uuid string, prog string, args []string, stdin io.Reader, stdout io.Writer) error {
        lockfile, err := func() (*os.File, error) {
                // We must hold the dir-level lock between
                // opening/creating the lockfile and acquiring LOCK_EX
@@ -99,10 +99,26 @@ func detach(uuid string, prog string, args []string, stdout, stderr io.Writer) e
        // from parent (sshd) while sending lockfile content to
        // caller.
        cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
+       // We need to manage our own OS pipe here to ensure the child
+       // process reads all of our stdin pipe before we return.
+       piper, pipew, err := os.Pipe()
+       if err != nil {
+               return err
+       }
+       defer pipew.Close()
+       cmd.Stdin = piper
        err = cmd.Start()
        if err != nil {
                return fmt.Errorf("exec %s: %s", cmd.Path, err)
        }
+       _, err = io.Copy(pipew, stdin)
+       if err != nil {
+               return err
+       }
+       err = pipew.Close()
+       if err != nil {
+               return err
+       }
 
        w := io.MultiWriter(stdout, lockfile)
        return json.NewEncoder(w).Encode(procinfo{