浏览代码

Merge pull request #4563 from creack/signal-improvment

Signal improvments
Michael Crosby 11 年之前
父节点
当前提交
b5a544b02e
共有 10 个文件被更改,包括 192 次插入153 次删除
  1. 18 7
      api/client.go
  2. 19 0
      pkg/signal/signal.go
  3. 40 0
      pkg/signal/signal_darwin.go
  4. 44 0
      pkg/signal/signal_freebsd.go
  5. 43 0
      pkg/signal/signal_linux.go
  6. 9 0
      pkg/signal/signal_unsupported.go
  7. 19 44
      server.go
  8. 0 11
      utils/signal.go
  9. 0 44
      utils/signal_darwin.go
  10. 0 47
      utils/signal_linux.go

+ 18 - 7
api/client.go

@@ -12,6 +12,7 @@ import (
 	"github.com/dotcloud/docker/engine"
 	"github.com/dotcloud/docker/engine"
 	"github.com/dotcloud/docker/nat"
 	"github.com/dotcloud/docker/nat"
 	flag "github.com/dotcloud/docker/pkg/mflag"
 	flag "github.com/dotcloud/docker/pkg/mflag"
+	"github.com/dotcloud/docker/pkg/signal"
 	"github.com/dotcloud/docker/pkg/term"
 	"github.com/dotcloud/docker/pkg/term"
 	"github.com/dotcloud/docker/registry"
 	"github.com/dotcloud/docker/registry"
 	"github.com/dotcloud/docker/runconfig"
 	"github.com/dotcloud/docker/runconfig"
@@ -23,7 +24,7 @@ import (
 	"net/http/httputil"
 	"net/http/httputil"
 	"net/url"
 	"net/url"
 	"os"
 	"os"
-	"os/signal"
+	gosignal "os/signal"
 	"path"
 	"path"
 	"reflect"
 	"reflect"
 	"regexp"
 	"regexp"
@@ -532,13 +533,23 @@ func (cli *DockerCli) CmdRestart(args ...string) error {
 
 
 func (cli *DockerCli) forwardAllSignals(cid string) chan os.Signal {
 func (cli *DockerCli) forwardAllSignals(cid string) chan os.Signal {
 	sigc := make(chan os.Signal, 1)
 	sigc := make(chan os.Signal, 1)
-	utils.CatchAll(sigc)
+	signal.CatchAll(sigc)
 	go func() {
 	go func() {
 		for s := range sigc {
 		for s := range sigc {
 			if s == syscall.SIGCHLD {
 			if s == syscall.SIGCHLD {
 				continue
 				continue
 			}
 			}
-			if _, _, err := readBody(cli.call("POST", fmt.Sprintf("/containers/%s/kill?signal=%d", cid, s), nil, false)); err != nil {
+			var sig string
+			for sigStr, sigN := range signal.SignalMap {
+				if sigN == s {
+					sig = sigStr
+					break
+				}
+			}
+			if sig == "" {
+				utils.Errorf("Unsupported signal: %d. Discarding.", s)
+			}
+			if _, _, err := readBody(cli.call("POST", fmt.Sprintf("/containers/%s/kill?signal=%s", cid, sig), nil, false)); err != nil {
 				utils.Debugf("Error sending signal: %s", err)
 				utils.Debugf("Error sending signal: %s", err)
 			}
 			}
 		}
 		}
@@ -580,7 +591,7 @@ func (cli *DockerCli) CmdStart(args ...string) error {
 
 
 		if !container.Config.Tty {
 		if !container.Config.Tty {
 			sigc := cli.forwardAllSignals(cmd.Arg(0))
 			sigc := cli.forwardAllSignals(cmd.Arg(0))
-			defer utils.StopCatch(sigc)
+			defer signal.StopCatch(sigc)
 		}
 		}
 
 
 		var in io.ReadCloser
 		var in io.ReadCloser
@@ -1613,7 +1624,7 @@ func (cli *DockerCli) CmdAttach(args ...string) error {
 
 
 	if *proxy && !container.Config.Tty {
 	if *proxy && !container.Config.Tty {
 		sigc := cli.forwardAllSignals(cmd.Arg(0))
 		sigc := cli.forwardAllSignals(cmd.Arg(0))
-		defer utils.StopCatch(sigc)
+		defer signal.StopCatch(sigc)
 	}
 	}
 
 
 	if err := cli.hijack("POST", "/containers/"+cmd.Arg(0)+"/attach?"+v.Encode(), container.Config.Tty, in, cli.out, cli.err, nil); err != nil {
 	if err := cli.hijack("POST", "/containers/"+cmd.Arg(0)+"/attach?"+v.Encode(), container.Config.Tty, in, cli.out, cli.err, nil); err != nil {
@@ -1817,7 +1828,7 @@ func (cli *DockerCli) CmdRun(args ...string) error {
 
 
 	if sigProxy {
 	if sigProxy {
 		sigc := cli.forwardAllSignals(runResult.Get("Id"))
 		sigc := cli.forwardAllSignals(runResult.Get("Id"))
-		defer utils.StopCatch(sigc)
+		defer signal.StopCatch(sigc)
 	}
 	}
 
 
 	var (
 	var (
@@ -2319,7 +2330,7 @@ func (cli *DockerCli) monitorTtySize(id string) error {
 	cli.resizeTty(id)
 	cli.resizeTty(id)
 
 
 	sigchan := make(chan os.Signal, 1)
 	sigchan := make(chan os.Signal, 1)
-	signal.Notify(sigchan, syscall.SIGWINCH)
+	gosignal.Notify(sigchan, syscall.SIGWINCH)
 	go func() {
 	go func() {
 		for _ = range sigchan {
 		for _ = range sigchan {
 			cli.resizeTty(id)
 			cli.resizeTty(id)

+ 19 - 0
pkg/signal/signal.go

@@ -0,0 +1,19 @@
+package signal
+
+import (
+	"os"
+	"os/signal"
+)
+
+func CatchAll(sigc chan os.Signal) {
+	handledSigs := []os.Signal{}
+	for _, s := range SignalMap {
+		handledSigs = append(handledSigs, s)
+	}
+	signal.Notify(sigc, handledSigs...)
+}
+
+func StopCatch(sigc chan os.Signal) {
+	signal.Stop(sigc)
+	close(sigc)
+}

+ 40 - 0
pkg/signal/signal_darwin.go

@@ -0,0 +1,40 @@
+package signal
+
+import (
+	"syscall"
+)
+
+var SignalMap = map[string]syscall.Signal{
+	"ABRT":   syscall.SIGABRT,
+	"ALRM":   syscall.SIGALRM,
+	"BUG":    syscall.SIGBUS,
+	"CHLD":   syscall.SIGCHLD,
+	"CONT":   syscall.SIGCONT,
+	"EMT":    syscall.SIGEMT,
+	"FPE":    syscall.SIGFPE,
+	"HUP":    syscall.SIGHUP,
+	"ILL":    syscall.SIGILL,
+	"INFO":   syscall.SIGINFO,
+	"INT":    syscall.SIGINT,
+	"IO":     syscall.SIGIO,
+	"IOT":    syscall.SIGIOT,
+	"KILL":   syscall.SIGKILL,
+	"PIPE":   syscall.SIGPIPE,
+	"PROF":   syscall.SIGPROF,
+	"QUIT":   syscall.SIGQUIT,
+	"SEGV":   syscall.SIGSEGV,
+	"STOP":   syscall.SIGSTOP,
+	"SYS":    syscall.SIGSYS,
+	"TERM":   syscall.SIGTERM,
+	"TRAP":   syscall.SIGTRAP,
+	"TSTP":   syscall.SIGTSTP,
+	"TTIN":   syscall.SIGTTIN,
+	"TTOU":   syscall.SIGTTOU,
+	"URG":    syscall.SIGURG,
+	"USR1":   syscall.SIGUSR1,
+	"USR2":   syscall.SIGUSR2,
+	"VTALRM": syscall.SIGVTALRM,
+	"WINCH":  syscall.SIGWINCH,
+	"XCPU":   syscall.SIGXCPU,
+	"XFSZ":   syscall.SIGXFSZ,
+}

+ 44 - 0
pkg/signal/signal_freebsd.go

@@ -0,0 +1,44 @@
+package signal
+
+import (
+	"os"
+	"os/signal"
+	"syscall"
+)
+
+var SignalMap = map[string]syscall.Signal{
+	"ABRT":   syscall.SIGABRT,
+	"ALRM":   syscall.SIGALRM,
+	"BUF":    syscall.SIGBUS,
+	"CHLD":   syscall.SIGCHLD,
+	"CONT":   syscall.SIGCONT,
+	"EMT":    syscall.SIGEMT,
+	"FPE":    syscall.SIGFPE,
+	"HUP":    syscall.SIGHUP,
+	"ILL":    syscall.SIGILL,
+	"INFO":   syscall.SIGINFO,
+	"INT":    syscall.SIGINT,
+	"IO":     syscall.SIGIO,
+	"IOT":    syscall.SIGIOT,
+	"KILL":   syscall.SIGKILL,
+	"LWP":    syscall.SIGLWP,
+	"PIPE":   syscall.SIGPIPE,
+	"PROF":   syscall.SIGPROF,
+	"QUIT":   syscall.SIGQUIT,
+	"SEGV":   syscall.SIGSEGV,
+	"STOP":   syscall.SIGSTOP,
+	"SYS":    syscall.SIGSYS,
+	"TERM":   syscall.SIGTERM,
+	"THR":    syscall.SIGTHR,
+	"TRAP":   syscall.SIGTRAP,
+	"TSTP":   syscall.SIGTSTP,
+	"TTIN":   syscall.SIGTTIN,
+	"TTOU":   syscall.SIGTTOU,
+	"URG":    syscall.SIGURG,
+	"USR1":   syscall.SIGUSR1,
+	"USR2":   syscall.SIGUSR2,
+	"VTALRM": syscall.SIGVTALRM,
+	"WINCH":  syscall.SIGWINCH,
+	"XCPU":   syscall.SIGXCPU,
+	"XFSZ":   syscall.SIGXFSZ,
+}

+ 43 - 0
pkg/signal/signal_linux.go

@@ -0,0 +1,43 @@
+package signal
+
+import (
+	"syscall"
+)
+
+var SignalMap = map[string]syscall.Signal{
+	"ABRT":   syscall.SIGABRT,
+	"ALRM":   syscall.SIGALRM,
+	"BUS":    syscall.SIGBUS,
+	"CHLD":   syscall.SIGCHLD,
+	"CLD":    syscall.SIGCLD,
+	"CONT":   syscall.SIGCONT,
+	"FPE":    syscall.SIGFPE,
+	"HUP":    syscall.SIGHUP,
+	"ILL":    syscall.SIGILL,
+	"INT":    syscall.SIGINT,
+	"IO":     syscall.SIGIO,
+	"IOT":    syscall.SIGIOT,
+	"KILL":   syscall.SIGKILL,
+	"PIPE":   syscall.SIGPIPE,
+	"POLL":   syscall.SIGPOLL,
+	"PROF":   syscall.SIGPROF,
+	"PWR":    syscall.SIGPWR,
+	"QUIT":   syscall.SIGQUIT,
+	"SEGV":   syscall.SIGSEGV,
+	"STKFLT": syscall.SIGSTKFLT,
+	"STOP":   syscall.SIGSTOP,
+	"SYS":    syscall.SIGSYS,
+	"TERM":   syscall.SIGTERM,
+	"TRAP":   syscall.SIGTRAP,
+	"TSTP":   syscall.SIGTSTP,
+	"TTIN":   syscall.SIGTTIN,
+	"TTOU":   syscall.SIGTTOU,
+	"UNUSED": syscall.SIGUNUSED,
+	"URG":    syscall.SIGURG,
+	"USR1":   syscall.SIGUSR1,
+	"USR2":   syscall.SIGUSR2,
+	"VTALRM": syscall.SIGVTALRM,
+	"WINCH":  syscall.SIGWINCH,
+	"XCPU":   syscall.SIGXCPU,
+	"XFSZ":   syscall.SIGXFSZ,
+}

+ 9 - 0
pkg/signal/signal_unsupported.go

@@ -0,0 +1,9 @@
+// +build !linux,!darwin,!freebsd
+
+package signal
+
+import (
+	"syscall"
+)
+
+var SignalMap = map[string]syscall.Signal{}

+ 19 - 44
server.go

@@ -10,6 +10,7 @@ import (
 	"github.com/dotcloud/docker/graph"
 	"github.com/dotcloud/docker/graph"
 	"github.com/dotcloud/docker/image"
 	"github.com/dotcloud/docker/image"
 	"github.com/dotcloud/docker/pkg/graphdb"
 	"github.com/dotcloud/docker/pkg/graphdb"
+	"github.com/dotcloud/docker/pkg/signal"
 	"github.com/dotcloud/docker/registry"
 	"github.com/dotcloud/docker/registry"
 	"github.com/dotcloud/docker/runconfig"
 	"github.com/dotcloud/docker/runconfig"
 	"github.com/dotcloud/docker/runtime"
 	"github.com/dotcloud/docker/runtime"
@@ -21,7 +22,7 @@ import (
 	"net/url"
 	"net/url"
 	"os"
 	"os"
 	"os/exec"
 	"os/exec"
-	"os/signal"
+	gosignal "os/signal"
 	"path"
 	"path"
 	"path/filepath"
 	"path/filepath"
 	goruntime "runtime"
 	goruntime "runtime"
@@ -50,7 +51,7 @@ func InitServer(job *engine.Job) engine.Status {
 	}
 	}
 	job.Logf("Setting up signal traps")
 	job.Logf("Setting up signal traps")
 	c := make(chan os.Signal, 1)
 	c := make(chan os.Signal, 1)
-	signal.Notify(c, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT)
+	gosignal.Notify(c, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT)
 	go func() {
 	go func() {
 		sig := <-c
 		sig := <-c
 		log.Printf("Received signal '%v', exiting\n", sig)
 		log.Printf("Received signal '%v', exiting\n", sig)
@@ -126,56 +127,30 @@ func (v *simpleVersionInfo) Version() string {
 // for the container to exit.
 // for the container to exit.
 // If a signal is given, then just send it to the container and return.
 // If a signal is given, then just send it to the container and return.
 func (srv *Server) ContainerKill(job *engine.Job) engine.Status {
 func (srv *Server) ContainerKill(job *engine.Job) engine.Status {
-	signalMap := map[string]syscall.Signal{
-		"HUP":  syscall.SIGHUP,
-		"INT":  syscall.SIGINT,
-		"QUIT": syscall.SIGQUIT,
-		"ILL":  syscall.SIGILL,
-		"TRAP": syscall.SIGTRAP,
-		"ABRT": syscall.SIGABRT,
-		"BUS":  syscall.SIGBUS,
-		"FPE":  syscall.SIGFPE,
-		"KILL": syscall.SIGKILL,
-		"USR1": syscall.SIGUSR1,
-		"SEGV": syscall.SIGSEGV,
-		"USR2": syscall.SIGUSR2,
-		"PIPE": syscall.SIGPIPE,
-		"ALRM": syscall.SIGALRM,
-		"TERM": syscall.SIGTERM,
-		//"STKFLT": syscall.SIGSTKFLT,
-		"CHLD":   syscall.SIGCHLD,
-		"CONT":   syscall.SIGCONT,
-		"STOP":   syscall.SIGSTOP,
-		"TSTP":   syscall.SIGTSTP,
-		"TTIN":   syscall.SIGTTIN,
-		"TTOU":   syscall.SIGTTOU,
-		"URG":    syscall.SIGURG,
-		"XCPU":   syscall.SIGXCPU,
-		"XFSZ":   syscall.SIGXFSZ,
-		"VTALRM": syscall.SIGVTALRM,
-		"PROF":   syscall.SIGPROF,
-		"WINCH":  syscall.SIGWINCH,
-		"IO":     syscall.SIGIO,
-		//"PWR":    syscall.SIGPWR,
-		"SYS": syscall.SIGSYS,
-	}
-
 	if n := len(job.Args); n < 1 || n > 2 {
 	if n := len(job.Args); n < 1 || n > 2 {
 		return job.Errorf("Usage: %s CONTAINER [SIGNAL]", job.Name)
 		return job.Errorf("Usage: %s CONTAINER [SIGNAL]", job.Name)
 	}
 	}
-	name := job.Args[0]
-	var sig uint64
+	var (
+		name = job.Args[0]
+		sig  uint64
+		err  error
+	)
+
+	// If we have a signal, look at it. Otherwise, do nothing
 	if len(job.Args) == 2 && job.Args[1] != "" {
 	if len(job.Args) == 2 && job.Args[1] != "" {
-		sig = uint64(signalMap[job.Args[1]])
-		if sig == 0 {
-			var err error
-			// The largest legal signal is 31, so let's parse on 5 bits
-			sig, err = strconv.ParseUint(job.Args[1], 10, 5)
-			if err != nil {
+		// Check if we passed the singal as a number:
+		// The largest legal signal is 31, so let's parse on 5 bits
+		sig, err = strconv.ParseUint(job.Args[1], 10, 5)
+		if err != nil {
+			// The signal is not a number, treat it as a string
+			sig = uint64(signal.SignalMap[job.Args[1]])
+			if sig == 0 {
 				return job.Errorf("Invalid signal: %s", job.Args[1])
 				return job.Errorf("Invalid signal: %s", job.Args[1])
 			}
 			}
+
 		}
 		}
 	}
 	}
+
 	if container := srv.runtime.Get(name); container != nil {
 	if container := srv.runtime.Get(name); container != nil {
 		// If no signal is passed, or SIGKILL, perform regular Kill (SIGKILL + wait())
 		// If no signal is passed, or SIGKILL, perform regular Kill (SIGKILL + wait())
 		if sig == 0 || syscall.Signal(sig) == syscall.SIGKILL {
 		if sig == 0 || syscall.Signal(sig) == syscall.SIGKILL {

+ 0 - 11
utils/signal.go

@@ -1,11 +0,0 @@
-package utils
-
-import (
-	"os"
-	"os/signal"
-)
-
-func StopCatch(sigc chan os.Signal) {
-	signal.Stop(sigc)
-	close(sigc)
-}

+ 0 - 44
utils/signal_darwin.go

@@ -1,44 +0,0 @@
-package utils
-
-import (
-	"os"
-	"os/signal"
-	"syscall"
-)
-
-func CatchAll(sigc chan os.Signal) {
-	signal.Notify(sigc,
-		syscall.SIGABRT,
-		syscall.SIGALRM,
-		syscall.SIGBUS,
-		syscall.SIGCHLD,
-		syscall.SIGCONT,
-		syscall.SIGEMT,
-		syscall.SIGFPE,
-		syscall.SIGHUP,
-		syscall.SIGILL,
-		syscall.SIGINFO,
-		syscall.SIGINT,
-		syscall.SIGIO,
-		syscall.SIGIOT,
-		syscall.SIGKILL,
-		syscall.SIGPIPE,
-		syscall.SIGPROF,
-		syscall.SIGQUIT,
-		syscall.SIGSEGV,
-		syscall.SIGSTOP,
-		syscall.SIGSYS,
-		syscall.SIGTERM,
-		syscall.SIGTRAP,
-		syscall.SIGTSTP,
-		syscall.SIGTTIN,
-		syscall.SIGTTOU,
-		syscall.SIGURG,
-		syscall.SIGUSR1,
-		syscall.SIGUSR2,
-		syscall.SIGVTALRM,
-		syscall.SIGWINCH,
-		syscall.SIGXCPU,
-		syscall.SIGXFSZ,
-	)
-}

+ 0 - 47
utils/signal_linux.go

@@ -1,47 +0,0 @@
-package utils
-
-import (
-	"os"
-	"os/signal"
-	"syscall"
-)
-
-func CatchAll(sigc chan os.Signal) {
-	signal.Notify(sigc,
-		syscall.SIGABRT,
-		syscall.SIGALRM,
-		syscall.SIGBUS,
-		syscall.SIGCHLD,
-		syscall.SIGCLD,
-		syscall.SIGCONT,
-		syscall.SIGFPE,
-		syscall.SIGHUP,
-		syscall.SIGILL,
-		syscall.SIGINT,
-		syscall.SIGIO,
-		syscall.SIGIOT,
-		syscall.SIGKILL,
-		syscall.SIGPIPE,
-		syscall.SIGPOLL,
-		syscall.SIGPROF,
-		syscall.SIGPWR,
-		syscall.SIGQUIT,
-		syscall.SIGSEGV,
-		syscall.SIGSTKFLT,
-		syscall.SIGSTOP,
-		syscall.SIGSYS,
-		syscall.SIGTERM,
-		syscall.SIGTRAP,
-		syscall.SIGTSTP,
-		syscall.SIGTTIN,
-		syscall.SIGTTOU,
-		syscall.SIGUNUSED,
-		syscall.SIGURG,
-		syscall.SIGUSR1,
-		syscall.SIGUSR2,
-		syscall.SIGVTALRM,
-		syscall.SIGWINCH,
-		syscall.SIGXCPU,
-		syscall.SIGXFSZ,
-	)
-}