Skip to content

Commit adcb290

Browse files
committed
Fix hanging on runc create.
This reverts commit 0ab61ae, and also * changes ReadStandardStreams to use ioutils.ReadFile; * changes the uuid module used by the code (see commit abcb94d). Using bytes.Buffer instead of plain os.File results in go runtime creating two sets of pipes and spawning two threads (for stdout and stderr) that copy the data from the pipe to the buffers. It is not working when we execute runc create, because it spawns a child (runc init) whose stdout and stderr are kept connected to the write ends of the above pipes. As a result, those copying routines never finish, and cmd.Run() never returns as it waits for those routines. Therefore, let's go back to using temporary files. Note that the new code is using ioutil.ReadAll instead of reusing the opened file descriptors, which seems a bit cleaner. Signed-off-by: Kir Kolyshkin <[email protected]>
1 parent db715ee commit adcb290

File tree

2 files changed

+34
-12
lines changed

2 files changed

+34
-12
lines changed

validation/util/container.go

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
package util
22

33
import (
4-
"bytes"
54
"encoding/json"
65
"errors"
76
"fmt"
7+
"io/ioutil"
88
"os"
99
"os/exec"
1010
"path/filepath"
1111
"time"
1212

13+
"github.com/google/uuid"
1314
rspecs "github.com/opencontainers/runtime-spec/specs-go"
1415
"github.com/opencontainers/runtime-tools/generate"
1516
"github.com/opencontainers/runtime-tools/specerror"
@@ -21,8 +22,8 @@ type Runtime struct {
2122
BundleDir string
2223
PidFile string
2324
ID string
24-
stdout bytes.Buffer
25-
stderr bytes.Buffer
25+
stdout *os.File
26+
stderr *os.File
2627
}
2728

2829
// DefaultSignal represents the default signal sends to a container
@@ -78,18 +79,25 @@ func (r *Runtime) Create() (err error) {
7879
args = append(args, r.ID)
7980
}
8081
cmd := exec.Command(r.RuntimeCommand, args...)
81-
r.stdout.Reset()
82-
cmd.Stdout = &r.stdout
83-
r.stderr.Reset()
84-
cmd.Stderr = &r.stderr
82+
id := uuid.NewString()
83+
r.stdout, err = os.OpenFile(filepath.Join(r.bundleDir(), fmt.Sprintf("stdout-%s", id)), os.O_CREATE|os.O_EXCL|os.O_RDWR, 0600)
84+
if err != nil {
85+
return err
86+
}
87+
cmd.Stdout = r.stdout
88+
r.stderr, err = os.OpenFile(filepath.Join(r.bundleDir(), fmt.Sprintf("stderr-%s", id)), os.O_CREATE|os.O_EXCL|os.O_RDWR, 0600)
89+
if err != nil {
90+
return err
91+
}
92+
cmd.Stderr = r.stderr
8593

8694
err = cmd.Run()
8795
if err == nil {
8896
return err
8997
}
9098

9199
if e, ok := err.(*exec.ExitError); ok {
92-
stdout, stderr := r.StandardStreams()
100+
stdout, stderr, _ := r.ReadStandardStreams()
93101
if len(stderr) == 0 {
94102
stderr = stdout
95103
}
@@ -99,9 +107,14 @@ func (r *Runtime) Create() (err error) {
99107
return err
100108
}
101109

102-
// StandardStreams returns content from the stdout and stderr buffers.
103-
func (r *Runtime) StandardStreams() (stdout, stderr []byte) {
104-
return r.stdout.Bytes(), r.stderr.Bytes()
110+
// ReadStandardStreams collects content from the stdout and stderr buffers.
111+
func (r *Runtime) ReadStandardStreams() (stdout []byte, stderr []byte, err error) {
112+
stdout, err = ioutil.ReadFile(r.stdout.Name())
113+
stderr, err2 := ioutil.ReadFile(r.stderr.Name())
114+
if err == nil && err2 != nil {
115+
err = err2
116+
}
117+
return
105118
}
106119

107120
// Start a container

validation/util/test.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,16 @@ func RuntimeInsideValidate(g *generate.Generator, t *tap.T, f PreFunc) (err erro
228228
return err
229229
}
230230

231-
stdout, stderr := r.StandardStreams()
231+
stdout, stderr, err := r.ReadStandardStreams()
232+
if err != nil {
233+
if len(stderr) == 0 {
234+
stderr = stdout
235+
}
236+
os.Stderr.WriteString("failed to read standard streams\n")
237+
os.Stderr.Write(stderr)
238+
return err
239+
}
240+
232241
// Write stdout in the outter TAP
233242
if t != nil {
234243
diagnostic := map[string]string{

0 commit comments

Comments
 (0)