github.com/containers/libpod@v1.9.4-0.20220419124438-4284fd425507/test/e2e/run_signal_test.go (about)

     1  // +build !remoteclient
     2  
     3  package integration
     4  
     5  import (
     6  	"fmt"
     7  	"io"
     8  	"os"
     9  	"path/filepath"
    10  	"strings"
    11  	"syscall"
    12  	"time"
    13  
    14  	"github.com/containers/libpod/pkg/rootless"
    15  	. "github.com/containers/libpod/test/utils"
    16  	. "github.com/onsi/ginkgo"
    17  	. "github.com/onsi/gomega"
    18  	"golang.org/x/sys/unix"
    19  )
    20  
    21  const sigCatch = "trap \"echo FOO >> /h/fifo \" 8; echo READY >> /h/fifo; while :; do sleep 0.25; done"
    22  const sigCatch2 = "trap \"echo Received\" SIGFPE; while :; do sleep 0.25; done"
    23  
    24  var _ = Describe("Podman run with --sig-proxy", func() {
    25  	var (
    26  		tmpdir     string
    27  		err        error
    28  		podmanTest *PodmanTestIntegration
    29  	)
    30  
    31  	BeforeEach(func() {
    32  		tmpdir, err = CreateTempDirInTempDir()
    33  		if err != nil {
    34  			os.Exit(1)
    35  		}
    36  		podmanTest = PodmanTestCreate(tmpdir)
    37  		podmanTest.Setup()
    38  		podmanTest.SeedImages()
    39  	})
    40  
    41  	AfterEach(func() {
    42  		podmanTest.Cleanup()
    43  		f := CurrentGinkgoTestDescription()
    44  		processTestResult(f)
    45  
    46  	})
    47  
    48  	Specify("signals are forwarded to container using sig-proxy", func() {
    49  		if podmanTest.Host.Arch == "ppc64le" {
    50  			Skip("Doesn't work on ppc64le")
    51  		}
    52  		signal := syscall.SIGFPE
    53  		// Set up a socket for communication
    54  		udsDir := filepath.Join(tmpdir, "socket")
    55  		os.Mkdir(udsDir, 0700)
    56  		udsPath := filepath.Join(udsDir, "fifo")
    57  		syscall.Mkfifo(udsPath, 0600)
    58  		if rootless.IsRootless() {
    59  			podmanTest.RestoreArtifact(fedoraMinimal)
    60  		}
    61  		_, pid := podmanTest.PodmanPID([]string{"run", "-it", "-v", fmt.Sprintf("%s:/h:Z", udsDir), fedoraMinimal, "bash", "-c", sigCatch})
    62  
    63  		uds, _ := os.OpenFile(udsPath, os.O_RDONLY|syscall.O_NONBLOCK, 0600)
    64  		defer uds.Close()
    65  
    66  		// Wait for the script in the container to alert us that it is READY
    67  		counter := 0
    68  		for {
    69  			buf := make([]byte, 1024)
    70  			n, err := uds.Read(buf[:])
    71  			if err != nil && err != io.EOF {
    72  				fmt.Println(err)
    73  				return
    74  			}
    75  			data := string(buf[0:n])
    76  			if strings.Contains(data, "READY") {
    77  				break
    78  			}
    79  			time.Sleep(1 * time.Second)
    80  			if counter == 15 {
    81  				Fail("Timed out waiting for READY from container")
    82  			}
    83  			counter++
    84  		}
    85  		// Ok, container is up and running now and so is the script
    86  
    87  		if err := unix.Kill(pid, signal); err != nil {
    88  			Fail(fmt.Sprintf("error killing podman process %d: %v", pid, err))
    89  		}
    90  
    91  		// The sending of the signal above will send FOO to the socket; here we
    92  		// listen to the socket for that.
    93  		counter = 0
    94  		for {
    95  			buf := make([]byte, 1024)
    96  			n, err := uds.Read(buf[:])
    97  			if err != nil {
    98  				fmt.Println(err)
    99  				return
   100  			}
   101  			data := string(buf[0:n])
   102  			if strings.Contains(data, "FOO") {
   103  				break
   104  			}
   105  			time.Sleep(1 * time.Second)
   106  			if counter == 15 {
   107  				Fail("timed out waiting for FOO from container")
   108  			}
   109  			counter++
   110  		}
   111  	})
   112  
   113  	Specify("signals are not forwarded to container with sig-proxy false", func() {
   114  		signal := syscall.SIGFPE
   115  		if rootless.IsRootless() {
   116  			podmanTest.RestoreArtifact(fedoraMinimal)
   117  		}
   118  		session, pid := podmanTest.PodmanPID([]string{"run", "--name", "test2", "--sig-proxy=false", fedoraMinimal, "bash", "-c", sigCatch2})
   119  
   120  		ok := WaitForContainer(podmanTest)
   121  		Expect(ok).To(BeTrue())
   122  
   123  		// Kill with given signal
   124  		// Should be no output, SIGPOLL is usually ignored
   125  		if err := unix.Kill(pid, signal); err != nil {
   126  			Fail(fmt.Sprintf("error killing podman process %d: %v", pid, err))
   127  		}
   128  
   129  		// Kill with -9 to guarantee the container dies
   130  		killSession := podmanTest.Podman([]string{"kill", "-s", "9", "test2"})
   131  		killSession.WaitWithDefaultTimeout()
   132  		Expect(killSession.ExitCode()).To(Equal(0))
   133  
   134  		session.WaitWithDefaultTimeout()
   135  		Expect(session.ExitCode()).ToNot(Equal(0))
   136  		ok, _ = session.GrepString("Received")
   137  		Expect(ok).To(BeFalse())
   138  	})
   139  
   140  })