testcontainers-go icon indicating copy to clipboard operation
testcontainers-go copied to clipboard

[Bug]: container.Exec function hangs when output is large

Open yfzhou0904 opened this issue 9 months ago • 1 comments

Testcontainers version

0.34.0

Using the latest Testcontainers version?

Yes

Host OS

macOS

Host arch

ARM

Go version

1.22.3

Docker version

Client: Docker Engine - Community
 Version:           27.4.1
 API version:       1.41 (downgraded from 1.47)
 Go version:        go1.23.4
 Git commit:        b9d17eaebb
 Built:             Mon Dec 16 21:43:43 2024
 OS/Arch:           darwin/arm64
 Context:           default

Server: linux/arm64/fedora-40
 Podman Engine:
  Version:          5.3.1
  APIVersion:       5.3.1
  Arch:             arm64
  BuildTime:        2024-11-21T08:00:00+08:00
  Experimental:     false
  GitCommit:
  GoVersion:        go1.22.7
  KernelVersion:    6.11.3-200.fc40.aarch64
  MinAPIVersion:    4.0.0
  Os:               linux
 Conmon:
  Version:          conmon version 2.1.12, commit:
  Package:          conmon-2.1.12-2.fc40.aarch64
 OCI Runtime (crun):
  Version:          crun version 1.17
commit: 000fa0d4eeed8938301f3bcf8206405315bc1017
rundir: /run/crun
spec: 1.0.0
+SYSTEMD +SELINUX +APPARMOR +CAP +SECCOMP +EBPF +CRIU +LIBKRUN +WASM:wasmedge +YAJL
  Package:          crun-1.17-1.fc40.aarch64
 Engine:
  Version:          5.3.1
  API version:      1.41 (minimum version 1.24)
  Go version:       go1.22.7
  Git commit:
  Built:            Thu Nov 21 08:00:00 2024
  OS/Arch:          linux/arm64
  Experimental:     false

Docker info

Client: Docker Engine - Community
 Version:    27.4.1
 Context:    default
 Debug Mode: false
 Plugins:
WARNING: Plugin "/Users/yfzhou/.docker/cli-plugins/docker-buildx" is not valid: failed to fetch metadata: fork/exec /Users/yfzhou/.docker/cli-plugins/docker-buildx: no such file or directory
WARNING: Plugin "/Users/yfzhou/.docker/cli-plugins/docker-compose" is not valid: failed to fetch metadata: fork/exec /Users/yfzhou/.docker/cli-plugins/docker-compose: no such file or directory
WARNING: Plugin "/Users/yfzhou/.docker/cli-plugins/docker-debug" is not valid: failed to fetch metadata: fork/exec /Users/yfzhou/.docker/cli-plugins/docker-debug: no such file or directory
WARNING: Plugin "/Users/yfzhou/.docker/cli-plugins/docker-desktop" is not valid: failed to fetch metadata: fork/exec /Users/yfzhou/.docker/cli-plugins/docker-desktop: no such file or directory
WARNING: Plugin "/Users/yfzhou/.docker/cli-plugins/docker-dev" is not valid: failed to fetch metadata: fork/exec /Users/yfzhou/.docker/cli-plugins/docker-dev: no such file or directory
WARNING: Plugin "/Users/yfzhou/.docker/cli-plugins/docker-extension" is not valid: failed to fetch metadata: fork/exec /Users/yfzhou/.docker/cli-plugins/docker-extension: no such file or directory
WARNING: Plugin "/Users/yfzhou/.docker/cli-plugins/docker-feedback" is not valid: failed to fetch metadata: fork/exec /Users/yfzhou/.docker/cli-plugins/docker-feedback: no such file or directory
WARNING: Plugin "/Users/yfzhou/.docker/cli-plugins/docker-init" is not valid: failed to fetch metadata: fork/exec /Users/yfzhou/.docker/cli-plugins/docker-init: no such file or directory
WARNING: Plugin "/Users/yfzhou/.docker/cli-plugins/docker-sbom" is not valid: failed to fetch metadata: fork/exec /Users/yfzhou/.docker/cli-plugins/docker-sbom: no such file or directory
WARNING: Plugin "/Users/yfzhou/.docker/cli-plugins/docker-scout" is not valid: failed to fetch metadata: fork/exec /Users/yfzhou/.docker/cli-plugins/docker-scout: no such file or directory

Server:
 Containers: 4
  Running: 4
  Paused: 0
  Stopped: 0
 Images: 1
 Server Version: 5.3.1
 Storage Driver: overlay
  Using metacopy: true
  Supports shifting: true
  Supports volatile: true
  Backing Filesystem: xfs
  Supports d_type: true
  Native Overlay Diff: false
 Cgroup Driver: systemd
 Cgroup Version: 2
 Plugins:
  Volume: local
  Network: bridge macvlan ipvlan
  Log: k8s-file none passthrough journald
 Swarm: inactive
 Runtimes: runsc youki krun crun-vm crun-wasm kata ocijail runc runj crun
 Default Runtime: crun
 Init Binary:
 containerd version:
 runc version:
 init version:
 Security Options:
  seccomp
   Profile: default
  selinux
 Kernel Version: 6.11.3-200.fc40.aarch64
 Operating System: fedora
 OSType: linux
 Architecture: arm64
 CPUs: 2
 Total Memory: 5.357GiB
 Name: localhost.localdomain
 ID: 623fbc0a-78c1-4e28-a63d-a76670afe263
 Docker Root Dir: /var/lib/containers/storage
 Debug Mode: false
 No Proxy: There aren't any bypass domains set on USB 10/100/1000 LAN.
 Experimental: true
 Live Restore Enabled: false
 Product License: Apache-2.0

What happened?

exitCode, outputReader, err := container.Exec(context.Background(), []string{
	"bash", "-c",
	"yes \"This is a line of text\" | head -n 100000",
})

works fine, but (notice that the output size is increased 10x)

exitCode, outputReader, err := container.Exec(context.Background(), []string{
	"bash", "-c",
	"yes \"This is a line of text\" | head -n 1000000",
})

hangs indefinitely.

Relevant log output


Additional information

Code to reproduce the issue (tested on macOS with Podman and Linux. May need to vary the output size to reproduce issue on different systems):

package main

import (
	"context"
	"fmt"
	"io"
	"log"
	"log/slog"

	"github.com/testcontainers/testcontainers-go"
)

func main() {
	var c testcontainers.Container

	ctx := context.Background()
	cleanup := func() {
		if err := c.Terminate(context.Background()); err != nil {
			log.Fatalf("failed to terminate container: %s", err)
		}
	}
	defer cleanup()

	c, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
		ContainerRequest: testcontainers.ContainerRequest{
			Image: "debian:latest",
			Cmd:   []string{"sleep", "infinity"},
		},
	})
	if err != nil {
		slog.Error("failed to start container", "error", err.Error())
		return
	}
	c.Start(ctx)
	slog.Info("container started", "id", c.GetContainerID())

	code, output, err := c.Exec(ctx, []string{
		"bash", "-c",
		"yes \"This is a line of text\" | head -n 100000",
	})
	if err != nil {
		slog.Error("failed to exec command", "error", err.Error())
		return
	} else if code != 0 {
		slog.Error("command failed", "output", output)
		return
	}

	outputBytes, _ := io.ReadAll(output)
	fmt.Println(string(outputBytes))
}

yfzhou0904 avatar Dec 30 '24 09:12 yfzhou0904