From cd73a6904d3dc91f305c7415ab7bada8a976d815 Mon Sep 17 00:00:00 2001
From: Matthew Heon <matthew.heon@gmail.com>
Date: Sun, 4 Mar 2018 12:24:56 -0500
Subject: Add signal proxying to podman run, start, and attach

Also removes sig-proxy from 'podman create', where is does not
make sense.

Signed-off-by: Matthew Heon <matthew.heon@gmail.com>
---
 cmd/podman/attach.go   |  8 ++++++++
 cmd/podman/common.go   |  4 ----
 cmd/podman/create.go   |  2 --
 cmd/podman/run.go      | 11 ++++++++++-
 cmd/podman/sigproxy.go | 33 +++++++++++++++++++++++++++++++++
 cmd/podman/start.go    | 12 ++++++++++++
 6 files changed, 63 insertions(+), 7 deletions(-)
 create mode 100644 cmd/podman/sigproxy.go

(limited to 'cmd')

diff --git a/cmd/podman/attach.go b/cmd/podman/attach.go
index 7f7e4d192..20c1c306d 100644
--- a/cmd/podman/attach.go
+++ b/cmd/podman/attach.go
@@ -16,6 +16,10 @@ var (
 			Name:  "no-stdin",
 			Usage: "Do not attach STDIN. The default is false.",
 		},
+		cli.BoolTFlag{
+			Name:  "sig-proxy",
+			Usage: "proxy received signals to the process (default true)",
+		},
 		LatestFlag,
 	}
 	attachDescription = "The podman attach command allows you to attach to a running container using the container's ID or name, either to view its ongoing output or to control it interactively."
@@ -63,6 +67,10 @@ func attachCmd(c *cli.Context) error {
 		return errors.Errorf("you can only attach to running containers")
 	}
 
+	if c.BoolT("sig-proxy") {
+		ProxySignals(ctr)
+	}
+
 	if err := ctr.Attach(c.Bool("no-stdin"), c.String("detach-keys")); err != nil {
 		return errors.Wrapf(err, "error attaching to container %s", ctr.ID())
 	}
diff --git a/cmd/podman/common.go b/cmd/podman/common.go
index 60cc48803..93de80e29 100644
--- a/cmd/podman/common.go
+++ b/cmd/podman/common.go
@@ -334,10 +334,6 @@ var createFlags = []cli.Flag{
 		Usage: "Size of `/dev/shm`. The format is `<number><unit>`.",
 		Value: "65536k",
 	},
-	cli.BoolFlag{
-		Name:  "sig-proxy",
-		Usage: "Proxy received signals to the process (default true)",
-	},
 	cli.StringFlag{
 		Name:  "stop-signal",
 		Usage: "Signal to stop a container. Default is SIGTERM",
diff --git a/cmd/podman/create.go b/cmd/podman/create.go
index 462c56a51..efd7458ea 100644
--- a/cmd/podman/create.go
+++ b/cmd/podman/create.go
@@ -117,7 +117,6 @@ type createConfig struct {
 	Resources          createResourceConfig
 	Rm                 bool //rm
 	ShmDir             string
-	SigProxy           bool              //sig-proxy
 	StopSignal         syscall.Signal    // stop-signal
 	StopTimeout        uint              // stop-timeout
 	Sysctl             map[string]string //sysctl
@@ -715,7 +714,6 @@ func parseCreateOpts(c *cli.Context, runtime *libpod.Runtime, imageName string,
 		},
 		Rm:          c.Bool("rm"),
 		ShmDir:      shmDir,
-		SigProxy:    c.Bool("sig-proxy"),
 		StopSignal:  stopSignal,
 		StopTimeout: c.Uint("stop-timeout"),
 		Sysctl:      sysctl,
diff --git a/cmd/podman/run.go b/cmd/podman/run.go
index f68db9036..7b840a387 100644
--- a/cmd/podman/run.go
+++ b/cmd/podman/run.go
@@ -13,11 +13,16 @@ import (
 
 var runDescription = "Runs a command in a new container from the given image"
 
+var runFlags []cli.Flag = append(createFlags, cli.BoolTFlag{
+	Name:  "sig-proxy",
+	Usage: "proxy received signals to the process (default true)",
+})
+
 var runCommand = cli.Command{
 	Name:                   "run",
 	Usage:                  "run a command in a new container",
 	Description:            runDescription,
-	Flags:                  createFlags,
+	Flags:                  runFlags,
 	Action:                 runCmd,
 	ArgsUsage:              "IMAGE [COMMAND [ARG...]]",
 	SkipArgReorder:         true,
@@ -133,6 +138,10 @@ func runCmd(c *cli.Context) error {
 		return errors.Wrapf(err, "unable to start container %q", ctr.ID())
 	}
 
+	if c.BoolT("sig-proxy") {
+		ProxySignals(ctr)
+	}
+
 	// Wait for attach to complete
 	err = <-attachChan
 	if err != nil {
diff --git a/cmd/podman/sigproxy.go b/cmd/podman/sigproxy.go
new file mode 100644
index 000000000..fd1415dc6
--- /dev/null
+++ b/cmd/podman/sigproxy.go
@@ -0,0 +1,33 @@
+package main
+
+import (
+	"os"
+	"syscall"
+
+	"github.com/docker/docker/pkg/signal"
+	"github.com/projectatomic/libpod/libpod"
+	"github.com/sirupsen/logrus"
+)
+
+func ProxySignals(ctr *libpod.Container) {
+	sigBuffer := make(chan os.Signal, 128)
+	signal.CatchAll(sigBuffer)
+
+	logrus.Debugf("Enabling signal proxying")
+
+	go func() {
+		for s := range sigBuffer {
+			// Ignore SIGCHLD and SIGPIPE - these are mostly likely
+			// intended for the podman command itself.
+			if s == signal.SIGCHLD || s == signal.SIGPIPE {
+				continue
+			}
+
+			if err := ctr.Kill(uint(s.(syscall.Signal))); err != nil {
+				logrus.Errorf("Error forwarding signal %d to container %s: %v", s, ctr.ID(), err)
+			}
+		}
+	}()
+
+	return
+}
diff --git a/cmd/podman/start.go b/cmd/podman/start.go
index c90fab645..366d5c3fc 100644
--- a/cmd/podman/start.go
+++ b/cmd/podman/start.go
@@ -25,6 +25,10 @@ var (
 			Name:  "interactive, i",
 			Usage: "Keep STDIN open even if not attached",
 		},
+		cli.BoolFlag{
+			Name:  "sig-proxy",
+			Usage: "proxy received signals to the process",
+		},
 		LatestFlag,
 	}
 	startDescription = `
@@ -60,6 +64,10 @@ func startCmd(c *cli.Context) error {
 		return err
 	}
 
+	if c.Bool("sig-proxy") && !attach {
+		return errors.Wrapf(libpod.ErrInvalidArg, "you cannot use sig-proxy without --attach")
+	}
+
 	runtime, err := getRuntime(c)
 	if err != nil {
 		return errors.Wrapf(err, "error creating libpod runtime")
@@ -106,6 +114,10 @@ func startCmd(c *cli.Context) error {
 				return errors.Wrapf(err, "unable to start container %s", ctr.ID())
 			}
 
+			if c.Bool("sig-proxy") {
+				ProxySignals(ctr)
+			}
+
 			// Wait for attach to complete
 			err = <-attachChan
 			if err != nil {
-- 
cgit v1.2.3-54-g00ecf