Skip to content

Commit

Permalink
ci: fix a race in TestExecIn and TestExecInTTY
Browse files Browse the repository at this point in the history
Fixes: #4437
We can use a chan to wait the output from init process. After we received the content,
it means that the init process has started. Then we can exec into this container to use
ps command to check the init process and the exec process are both exist.

Signed-off-by: lifubang <[email protected]>
  • Loading branch information
lifubang committed Oct 15, 2024
1 parent d82235c commit f08116b
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 15 deletions.
65 changes: 50 additions & 15 deletions libcontainer/integration/execin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,37 @@ func TestExecIn(t *testing.T) {
// Execute a first process in the container
stdinR, stdinW, err := os.Pipe()
ok(t, err)
defer func() {
_ = stdinR.Close()
_ = stdinW.Close()
}()
stdoutR, stdoutW, err := os.Pipe()
ok(t, err)
defer func() {
_ = stdoutR.Close()
_ = stdoutW.Close()
}()

ch := waitStdOut(stdoutR)
process := &libcontainer.Process{
Cwd: "/",
Args: []string{"cat"},
Env: standardEnvironment,
Stdin: stdinR,
Init: true,
Cwd: "/",
Args: []string{"cat", "/proc/self/cmdline", "-"},
Env: standardEnvironment,
Stdin: stdinR,
Stdout: stdoutW,
Init: true,
}
err = container.Run(process)
_ = stdinR.Close()
defer stdinW.Close() //nolint: errcheck
defer func() {
_, _ = stdinW.Write([]byte("hello"))
_ = stdinW.Close()
if _, err := process.Wait(); err != nil {
t.Log(err)
}
}()
ok(t, err)

err = <-ch
ok(t, err)

buffers := newStdBuffers()
Expand All @@ -55,8 +76,6 @@ func TestExecIn(t *testing.T) {
err = container.Run(ps)
ok(t, err)
waitProcess(ps, t)
_ = stdinW.Close()
waitProcess(process, t)

out := buffers.Stdout.String()
if !strings.Contains(out, "cat") || !strings.Contains(out, "ps") {
Expand Down Expand Up @@ -242,23 +261,39 @@ func TestExecInTTY(t *testing.T) {
// Execute a first process in the container
stdinR, stdinW, err := os.Pipe()
ok(t, err)
defer func() {
_ = stdinR.Close()
_ = stdinW.Close()
}()
stdoutR, stdoutW, err := os.Pipe()
ok(t, err)
defer func() {
_ = stdoutR.Close()
_ = stdoutW.Close()
}()

ch := waitStdOut(stdoutR)
process := &libcontainer.Process{
Cwd: "/",
Args: []string{"cat"},
Env: standardEnvironment,
Stdin: stdinR,
Init: true,
Cwd: "/",
Args: []string{"cat", "/proc/self/cmdline", "-"},
Env: standardEnvironment,
Stdin: stdinR,
Stdout: stdoutW,
Init: true,
}
err = container.Run(process)
_ = stdinR.Close()
defer func() {
_, _ = stdinW.Write([]byte("hello"))
_ = stdinW.Close()
if _, err := process.Wait(); err != nil {
t.Log(err)
}
}()
ok(t, err)

err = <-ch
ok(t, err)

ps := &libcontainer.Process{
Cwd: "/",
Args: []string{"ps"},
Expand Down
22 changes: 22 additions & 0 deletions libcontainer/integration/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -231,3 +231,25 @@ func runContainerOk(t *testing.T, config *configs.Config, args ...string) *stdBu
func destroyContainer(container *libcontainer.Container) {
_ = container.Destroy()
}

func waitStdOut(stdout *os.File) chan error {
ch := make(chan error, 1)
buf := make([]byte, 1)
go func() {
defer close(ch)

for {
n, err := stdout.Read(buf)
if err != nil {
ch <- err
return
}

if n >= 0 {
ch <- nil
return
}
}
}()
return ch
}

0 comments on commit f08116b

Please sign in to comment.